### load obs data
upDir <- "D:/R/CombinedData/"
obsData <- "D:/R/CombinedData/"
obsAll <- read.table(paste0(obsData, "ObsAll.txt"),
header = TRUE)
obsA1<- obsAll %>%
dplyr::filter(Collection=="2000_2002")%>%
mutate(StartDate=dmy(StartDate),MidDate=dmy(MidDate),FinishDate=dmy(FinishDate),Clock.Today=dmy(Clock.Today)) %>%
#mutate(SowingDate=as.factor(ifelse(SowingDate=="no","Sd_No",paste0("Sd_",SowingDate)))) %>% # assume this is typo to be fixed?
mutate(GrowthSeason1=as.factor(paste0("Gs_",GrowthSeason))) %>% # creating more intuitive labels here
mutate(Rotation1=as.factor(paste0("Rt_",Rotation))) %>%
mutate(ExpUnitCode=as.factor(paste0(Name,GrowthSeason1,Rotation1))) %>%
mutate(Clock.Today1 = as.POSIXct(paste(Clock.Today,Time),format="%Y-%m-%d %H:%M:%S"))%>%
mutate(GrowthSeason2=as.factor(paste0("Y",GrowthSeason,"(",Period,")"))) %>%
mutate(Rotation2=as.factor(ifelse(Rotation=="1",paste0("S",Rotation),paste0("R",Rotation))))
obsA4<- obsAll %>%
dplyr::filter(Collection=="2014_2018")%>%
mutate(StartDate=dmy(StartDate),MidDate=dmy(MidDate),FinishDate=dmy(FinishDate),Clock.Today=dmy(Clock.Today)) %>%
#mutate(SowingDate=as.factor(ifelse(SowingDate=="no","Sd_No",paste0("Sd_",SowingDate)))) %>% # assume this is typo to be fixed?
mutate(GrowthSeason1=as.factor(paste0("Gs_",GrowthSeason))) %>% # creating more intuitive labels here
mutate(Rotation1=as.factor(paste0("Rt_",Rotation))) %>%
mutate(ExpUnitCode=as.factor(paste0(Name,GrowthSeason1,Rotation1))) %>%
mutate(Clock.Today1 = as.POSIXct(paste(Clock.Today,Time),format="%Y-%m-%d %H:%M:%S"))%>%
mutate(GrowthSeason2=as.factor(paste0("Y",GrowthSeason,"(",Period,")"))) %>%
mutate(Rotation2=as.factor(ifelse(Rotation=="1",paste0("S",Rotation),paste0("R",Rotation))))
obsA2<- obsAll %>%
dplyr::filter(Collection=="1997_2001")%>%
mutate(StartDate=dmy(StartDate),MidDate=dmy(MidDate),FinishDate=dmy(FinishDate),Clock.Today=dmy(Clock.Today)) %>%
#mutate(SowingDate=as.factor(ifelse(SowingDate=="no","Sd_No",paste0("Sd_",SowingDate)))) %>% # assume this is typo to be fixed?
mutate(GrowthSeason1=as.factor(paste0("Gs_",GrowthSeason))) %>% # creating more intuitive labels here
mutate(Rotation1=as.factor(paste0("Rt_",Rotation))) %>%
mutate(ExpUnitCode=as.factor(paste0(Name,GrowthSeason1,Rotation1))) %>%
mutate(Clock.Today1 = as.POSIXct(paste(Clock.Today,Time),format="%Y-%m-%d %H:%M:%S"))%>%
mutate(GrowthSeason2=as.factor(paste0("Y",GrowthSeason,"(",Period,")"))) %>%
mutate(Rotation2=as.factor(paste0("R",Rotation)))
obsA3<- obsAll %>%
dplyr::filter(Collection=="2002_2004")%>%
mutate(StartDate=dmy(StartDate),MidDate=dmy(MidDate),FinishDate=dmy(FinishDate),Clock.Today=dmy(Clock.Today)) %>%
#mutate(SowingDate=as.factor(ifelse(SowingDate=="no","Sd_No",paste0("Sd_",SowingDate)))) %>% # assume this is typo to be fixed?
mutate(GrowthSeason1=as.factor(paste0("Gs_",GrowthSeason))) %>% # creating more intuitive labels here
mutate(Rotation1=as.factor(paste0("Rt_",Rotation))) %>%
mutate(ExpUnitCode=as.factor(paste0(Name,GrowthSeason1,Rotation1))) %>%
mutate(Clock.Today1 = as.POSIXct(paste(Clock.Today,Time),format="%Y-%m-%d %H:%M:%S"))%>%
mutate(GrowthSeason2=as.factor(paste0("Y",GrowthSeason,"(",Period,")"))) %>%
mutate(Rotation2=as.factor(paste0("R",Rotation)))
obsA<-rbind(obsA2,obsA3,obsA1,obsA4)
summary(obsA)
Clock.Today Name Collection Experiment Water
Min. :1997-01-28 Iversen_91DefoliationLL :895 1997_2001: 955 Lincoln2000:1218 dry: 973
1st Qu.:2001-02-10 Iversen_121DefoliationLLFDFD5 :777 2000_2002:1067 Lincoln2015:1132 irr:3078
Median :2002-08-22 Iversen_8Waterirr :494 2002_2004: 895 Lincoln2001: 387
Mean :2005-09-21 Iversen_8Waterdry :461 2010_2012: 0 Lincoln2003: 384
3rd Qu.:2015-03-09 Iversen_121DefoliationHHFDFD5 :288 2014_2018:1134 Lincoln2002: 257
Max. :2018-01-15 Iversen_9SowingDateSD1Waterirr:277 Lincoln2004: 254
(Other) :859 (Other) : 419
Defoliation SowingDate FD Period GrowthSeason Rotation StartDate
HH: 288 No :1850 FD10: 35 00_01 :995 Min. :1.000 Min. :1.000 Min. :1996-11-01
LL:3763 no :1134 FD2 : 34 01_02 :522 1st Qu.:1.000 1st Qu.:1.000 1st Qu.:2000-12-27
SD1 : 536 FD5 :3982 02_03 :432 Median :2.000 Median :3.000 Median :2002-06-14
SD2 : 199 03_04 :412 Mean :2.277 Mean :2.983 Mean :2005-08-15
SD3 : 169 15_16 :410 3rd Qu.:3.000 3rd Qu.:4.000 3rd Qu.:2015-01-30
SD4 : 163 16_17 :342 Max. :6.000 Max. :7.000 Max. :2017-12-04
(Other): 0 (Other):938
MidDate FinishDate Interval Variable VariableUnits Time
Min. :1996-12-27 Min. :1997-02-21 Min. : 0.00 NodeNumber :792 % : 220 12:00:00:4051
1st Qu.:2001-02-10 1st Qu.:2001-03-06 1st Qu.: 19.00 Height :697 cm : 454
Median :2002-08-09 Median :2002-10-05 Median : 32.00 shootbiomass:585 fractio0l: 833
Mean :2005-09-14 Mean :2005-10-15 Mean : 36.97 LAI :538 Fraction : 434
3rd Qu.:2015-03-13 3rd Qu.:2015-04-24 3rd Qu.: 48.00 SWC :284 kg/ha :1045
Max. :2017-12-25 Max. :2018-01-15 Max. :122.00 Fraction :220 m2/m2 : 538
(Other) :935 mm : 527
Observed StdDEV ExperimentID TreatmentID ID GrowthSeason1 Rotation1
Min. : 0.00 Min. : 0.0000 E1: 955 ILL :1389 E3ILL :895 Gs_1:1352 Rt_1:1175
1st Qu.: 3.50 1st Qu.: 0.0000 E2:1067 ILLF5 : 777 E5ILLF5:777 Gs_2:1447 Rt_2: 823
Median : 12.47 Median : 0.2582 E3: 895 DLL : 461 E1ILL :494 Gs_3: 530 Rt_3: 613
Mean : 585.40 Mean : 88.3883 E4: 0 IHHF5 : 288 E1DLL :461 Gs_4: 272 Rt_4: 458
3rd Qu.: 623.15 3rd Qu.: 30.3450 E5:1134 ILLS1 : 277 E5IHHF5:288 Gs_5: 399 Rt_5: 443
Max. :8556.38 Max. :2532.5264 DLLS1 : 259 E2ILLS1:277 Gs_6: 51 Rt_6: 397
NA's :1192 (Other): 600 (Other):859 Rt_7: 142
ExpUnitCode Clock.Today1 GrowthSeason2 Rotation2
Iversen_91DefoliationLLGs_2Rt_1: 84 Min. :1997-01-28 12:00:00 Y1(00_01): 596 R2 :823
Iversen_91DefoliationLLGs_1Rt_1: 72 1st Qu.:2001-02-10 12:00:00 Y1(02_03): 432 S1 :768
Iversen_91DefoliationLLGs_1Rt_4: 67 Median :2002-08-22 12:00:00 Y2(01_02): 428 R3 :613
Iversen_91DefoliationLLGs_1Rt_5: 67 Mean :2005-09-21 17:05:34 Y2(03_04): 412 R4 :458
Iversen_91DefoliationLLGs_1Rt_3: 66 3rd Qu.:2015-03-09 12:00:00 Y2(15_16): 410 R5 :443
Iversen_91DefoliationLLGs_1Rt_6: 62 Max. :2018-01-15 12:00:00 Y5(00_01): 399 R1 :407
(Other) :3633 (Other) :1374 (Other):539
obsA
upDir <- "D:/R/"
obsData <- "D:/R/TtAll/"
Tt<- read.table(paste0(obsData, "df.all.txt"),
header = TRUE)
TtA <- Tt %>% mutate(Clock.Today=dmy(Clock.Today), ExpUnitCode=as.factor(ExpName))
TtA
ObsH <-merge(obsA,TtA,by=c("Clock.Today","ExpUnitCode")) %>%
mutate(GrowthRotation=as.factor(paste0(GrowthSeason.x,Rotation.x)))%>%
dplyr::filter(Water.x=="irr")%>%
dplyr::filter(Defoliation.x=="LL")%>%
dplyr::filter(Variable=="NodeNumber")
summary(ObsH)
Clock.Today ExpUnitCode Name
Min. :1997-10-23 Iversen_121DefoliationLLFDFD5Gs_1Rt_1 : 85 Iversen_121DefoliationLLFDFD5 :605
1st Qu.:2000-12-23 Iversen_9SowingDateSD3WaterirrGs_1Rt_1: 60 Iversen_8Waterirr :605
Median :2002-01-08 Iversen_8WaterirrGs_4Rt_5 : 55 Iversen_91DefoliationLL :455
Mean :2005-06-12 Iversen_9SowingDateSD2WaterirrGs_1Rt_1: 55 Iversen_9SowingDateSD1Waterirr:300
3rd Qu.:2014-11-30 Iversen_9SowingDateSD4WaterirrGs_1Rt_1: 55 Iversen_9SowingDateSD2Waterirr:110
Max. :2018-01-15 Iversen_8WaterirrGs_5Rt_1 : 50 Iversen_9SowingDateSD3Waterirr:100
(Other) :1895 (Other) : 80
Collection Experiment.x Water.x Defoliation.x SowingDate.x FD.x Period
1997_2001:605 Lincoln2000:755 dry: 0 HH: 0 No :1060 FD10: 0 00_01 :630
2000_2002:590 Lincoln2015:605 irr:2255 LL:2255 no : 605 FD2 : 0 99_00 :230
2002_2004:455 Lincoln2003:225 SD1 : 300 FD5 :2255 02_03 :215
2010_2012: 0 Lincoln2001:185 SD2 : 110 03_04 :205
2014_2018:605 Lincoln1999:140 SD3 : 100 16_17 :195
Lincoln2004:140 SD4 : 80 15_16 :175
(Other) :205 (Other): 0 (Other):605
GrowthSeason.x Rotation.x StartDate MidDate FinishDate
Min. :1.000 Min. :1.000 Min. :1997-10-07 Min. :1997-10-28 Min. :1997-11-19
1st Qu.:1.000 1st Qu.:1.000 1st Qu.:2000-11-14 1st Qu.:2000-12-29 1st Qu.:2001-02-13
Median :2.000 Median :3.000 Median :2001-12-22 Median :2002-01-16 Median :2002-02-11
Mean :2.317 Mean :3.118 Mean :2005-05-10 Mean :2005-06-08 Mean :2005-07-08
3rd Qu.:3.000 3rd Qu.:5.000 3rd Qu.:2014-11-03 3rd Qu.:2014-12-16 3rd Qu.:2015-01-29
Max. :5.000 Max. :7.000 Max. :2017-12-04 Max. :2017-12-25 Max. :2018-01-15
Interval Variable VariableUnits Time Observed StdDEV
Min. : 0.00 NodeNumber:2255 % : 0 12:00:00:2255 Min. : 0.000 Min. :0.0000
1st Qu.: 17.00 Branch : 0 cm : 0 1st Qu.: 5.100 1st Qu.:0.0000
Median : 29.00 CrownWt : 0 fractio0l:1650 Median : 7.800 Median :0.2600
Mean : 32.86 Fraction : 0 Fraction : 605 Mean : 7.668 Mean :0.3549
3rd Qu.: 40.00 HardStemWt: 0 kg/ha : 0 3rd Qu.:10.400 3rd Qu.:0.5774
Max. :116.00 Height : 0 m2/m2 : 0 Max. :16.667 Max. :2.1000
(Other) : 0 mm : 0 NA's :520
ExperimentID TreatmentID ID GrowthSeason1 Rotation1 Clock.Today1
E1:605 ILL :1060 E1ILL :605 Gs_1:805 Rt_1:615 Min. :1997-10-23 12:00:00
E2:590 ILLF5 : 605 E5ILLF5:605 Gs_2:645 Rt_2:430 1st Qu.:2000-12-23 12:00:00
E3:455 ILLS1 : 300 E3ILL :455 Gs_3:300 Rt_3:325 Median :2002-01-08 12:00:00
E4: 0 ILLS2 : 110 E2ILLS1:300 Gs_4:295 Rt_4:275 Mean :2005-06-12 20:46:57
E5:605 ILLS3 : 100 E2ILLS2:110 Gs_5:210 Rt_5:265 3rd Qu.:2014-11-30 12:00:00
ILLS4 : 80 E2ILLS3:100 Gs_6: 0 Rt_6:260 Max. :2018-01-15 12:00:00
(Other): 0 (Other): 80 Rt_7: 85
GrowthSeason2 Rotation2 year day rain maxt mint
Y1(00_01):420 R2 :430 Min. :1997 Min. : 1.0 Min. : 0.0000 Min. : 7.90 Min. :-4.90
Y4(99_00):230 S1 :420 1st Qu.:2000 1st Qu.: 63.0 1st Qu.: 0.0000 1st Qu.:15.10 1st Qu.: 4.70
Y1(02_03):215 R3 :325 Median :2002 Median :138.0 Median : 0.0000 Median :18.80 Median : 8.60
Y5(00_01):210 R4 :275 Mean :2005 Mean :171.9 Mean : 0.9233 Mean :19.02 Mean : 7.97
Y2(03_04):205 R5 :265 3rd Qu.:2014 3rd Qu.:297.0 3rd Qu.: 0.0000 3rd Qu.:22.00 3rd Qu.:11.30
Y3(16_17):195 R6 :260 Max. :2018 Max. :365.0 Max. :35.3000 Max. :33.80 Max. :20.60
(Other) :780 (Other):280
mean radn wind vp Pp Tb TTbeta
Min. : 2.55 Min. : 1.30 Min. :0.600 Min. : 5.10 Min. :10.02 Min. :1 Min. : 0.03021
1st Qu.:10.50 1st Qu.: 9.70 1st Qu.:2.800 1st Qu.:10.08 1st Qu.:12.15 1st Qu.:2 1st Qu.: 2.12367
Median :13.20 Median :16.40 Median :3.900 Median :11.60 Median :14.28 Median :3 Median : 3.87643
Mean :13.49 Mean :16.89 Mean :3.923 Mean :11.91 Mean :13.96 Mean :3 Mean : 5.43220
3rd Qu.:16.50 3rd Qu.:23.10 3rd Qu.:4.800 3rd Qu.:14.00 3rd Qu.:15.92 3rd Qu.:4 3rd Qu.: 7.68109
Max. :26.20 Max. :34.50 Max. :9.300 Max. :22.90 Max. :16.65 Max. :5 Max. :23.34334
Tbb TTbroken TbF TTfick ExpName
Min. :1 Min. : 0.6683 Min. :1 Min. : 0.6683 Iversen_121DefoliationLLFDFD5Gs_1Rt_1 : 85
1st Qu.:2 1st Qu.: 6.3519 1st Qu.:2 1st Qu.: 6.9410 Iversen_9SowingDateSD3WaterirrGs_1Rt_1: 60
Median :3 Median : 8.7409 Median :3 Median : 9.6773 Iversen_8WaterirrGs_4Rt_5 : 55
Mean :3 Mean : 9.1513 Mean :3 Mean : 9.8401 Iversen_9SowingDateSD2WaterirrGs_1Rt_1: 55
3rd Qu.:4 3rd Qu.:11.7322 3rd Qu.:4 3rd Qu.:12.7247 Iversen_9SowingDateSD4WaterirrGs_1Rt_1: 55
Max. :5 Max. :20.2576 Max. :5 Max. :20.8129 Iversen_8WaterirrGs_5Rt_1 : 50
(Other) :1895
Experiment.y Water.y Defoliation.y SowingDate.y FD.y GrowthSeason.y Rotation.y
Lincoln1997:605 dry: 0 HH: 0 No :1060 FD10: 0 Gs_1:805 Rt_1 :615
Lincoln2000:510 irr:2255 LL:2255 no : 605 FD2 : 0 Gs_2:645 Rt_2 :430
Lincoln2001: 80 LS: 0 SD1 : 300 FD5 :2255 Gs_3:300 Rt_3 :325
Lincoln2002:455 SL: 0 SD2 : 110 Gs_4:295 Rt_4 :275
Lincoln2010: 0 SS: 0 SD3 : 100 Gs_5:210 Rt_5 :265
Lincoln2015:605 SD4 : 80 Gs_6: 0 Rt_6 :260
(Other): 0 (Other): 85
Tt_beta_sum Tt_fick_sum Tt_broken_sum Ppm Tmean GrowthRotation
Min. : 0.0967 Min. : 1.36 Min. : 1.36 Min. :10.25 Min. : 7.024 11 : 330
1st Qu.: 63.1925 1st Qu.: 162.47 1st Qu.: 151.24 1st Qu.:11.99 1st Qu.:11.337 12 : 190
Median :122.2336 Median : 274.04 Median : 254.09 Median :14.52 Median :13.963 13 : 115
Mean :152.1671 Mean : 298.79 Mean : 276.59 Mean :13.89 Mean :13.282 21 : 115
3rd Qu.:211.0533 3rd Qu.: 401.50 3rd Qu.: 372.81 3rd Qu.:15.99 3rd Qu.:15.771 26 : 115
Max. :722.6708 Max. :1186.65 Max. :1051.88 Max. :16.55 Max. :19.327 22 : 110
(Other):1280
mytheme1<-theme(
panel.spacing=unit(.01, "lines"),
panel.border = element_rect(colour = "black",size=1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black",size = 1),
axis.text.x = element_text(face = "plain", color = "black", size = 14,angle=90, vjust=0.5, hjust = 1),
axis.text.y = element_text(face = "plain", color = "black", size = 14),
axis.title.x=element_text(face="bold",colour="black",size = 14),
axis.title.y=element_text(face="bold",colour="black",size = 14),
strip.background = element_rect(colour = "black", fill = "white",size=1),
strip.text.x = element_text(size=14, angle=0, face = "plain"),
strip.text.y = element_text(size=14, face="plain"),
legend.title = element_text(colour="black", size=14, face="bold"),
axis.text = element_text(face = "bold", vjust = 0.5, size = 14))
mytheme3<-theme(
legend.title = element_text(colour="black", size=14, face="bold"),
legend.text = element_text(colour="black", size = 14,face="plain"),
panel.spacing=unit(.01, "lines"),
panel.border = element_rect(colour = "black",size=1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black",size = 1),
axis.text.x = element_text(face = "plain", color = "black", size = 14, vjust=0.5, hjust = 1),
axis.text.y = element_text(face = "plain", color = "black", size = 14),
axis.title.x=element_text(face="bold",colour="black",size = 14),
axis.title.y=element_text(face="bold",colour="black",size = 14),
strip.background = element_rect(colour = "black", fill = "white",size=1),
strip.text.x = element_text(size=14, angle=0, face = "plain"),
strip.text.y = element_text(size=14, face="plain"),
axis.text = element_text(face = "bold", vjust = 0.5, size = 14),
legend.position = "right", legend.box = "vertical")
Examples for order text
x1 <- c("white","white","blue","green","red","blue","red")
ord <- c("red","white","blue","green")
f1 <- factor(x1,levels=ord)
sort(f1)
[1] red red white white blue blue green
Levels: red white blue green
x2 <- as.character(sort(f1))
x <- c("white","white","blue","green","red","blue","red")
y <- c("red","white","blue","green")
x[order(match(x, y))]
[1] "red" "red" "white" "white" "blue" "blue" "green"
obsNode<-ObsH%>%
dplyr::filter(Tb==1)
obsNode0<-obsNode%>%
dplyr::filter(Name=="Iversen_8Waterirr")
obsNode0$Rotation2<- factor(obsNode0$Rotation2, levels=c("R1", "R2", "R3", "R4", "R5","R6", "R7"))
obsNode0%>%
ggplot(aes(x=Tt_broken_sum, y=Observed))+geom_point(size=2)+theme_bw()+xlab("Thermal time (°Cd) ")+ylab("Node number")+ggtitle(paste0("E1ILL","(Iversen_8Waterirr)")) +
scale_x_continuous(breaks = seq(0, 550, by =200), limits=c(0,450))+
scale_y_continuous(breaks = seq(0, 18, by =6), limits=c(0,16))+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="blue")+
facet_grid(GrowthSeason2~Rotation2)+mytheme1

#to save a final graph
#ggsave("D:/R/Pictures/Node/Iversen_8Waterirrnode.png", width=8, height=6, dpi=500)
#fig.height=4, fig.width=8
obsNode1<-obsNode%>%
#dplyr::filter(Ture!="No")%>%
dplyr::filter(Collection=="2000_2002")%>%
dplyr::filter(Name=="Iversen_9SowingDateSD1Waterirr")
obsNode1$Rotation2<- factor(obsNode1$Rotation2, levels=c("S1", "R2", "R3", "R4", "R5","R6"))
obsNode1%>%
ggplot(aes(x=Tt_beta_sum, y=Observed), colour=factor(Name))+geom_point(size=2)+theme_bw()+xlab("Thermal time (°Cd) ")+scale_x_continuous(limits=c(0,425))+
ylab("Node number")+ggtitle(paste0("E2ILLS1","(Iversen_9SowingDateSD1Waterirr)"))+
scale_x_continuous(breaks = seq(0, 550, by =200), limits=c(0,450))+
scale_y_continuous(breaks = seq(0, 18, by =6), limits=c(0,16))+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="blue")+
facet_grid(GrowthSeason2~Rotation2)+
theme(axis.title.y=element_text(face="bold",colour="black",size = 14))+mytheme1
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.

#ggsave("D:/R/Pictures/Node/Iversen_9SowingDateSD1Waterirrnode.png", width=8, height=4, dpi=500)
obsNode2<-obsNode%>%
#dplyr::filter(Ture!="No")%>%
dplyr::filter(Collection=="2000_2002")%>%
dplyr::filter(Name=="Iversen_9SowingDateSD2Waterirr")
obsNode2$Rotation2<- factor(obsNode2$Rotation2, levels=c("S1", "R2", "R3", "R4", "R5","R6"))
obsNode2%>%
ggplot(aes(x=Tt_beta_sum, y=Observed), colour=factor(Name))+geom_point(size=2)+theme_bw()+xlab("Thermal time (°Cd)")+ylab("Node number")+ggtitle(paste0("E2ILLS2","(Iversen_9SowingDateSD2Waterirr)"))+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="blue")+
facet_grid(GrowthSeason2~Rotation2)+
scale_x_continuous(breaks = seq(0, 550, by =200), limits=c(0,450))+
scale_y_continuous(breaks = seq(0, 18, by =6), limits=c(0,16))+
#remove grid lines
theme(
panel.spacing=unit(.01, "lines"),
panel.border = element_rect(colour = "black",size=1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black",size = 1),
axis.text.x = element_text(face = "plain", color = "black", size = 14, vjust=0.5, hjust = 1),
axis.text.y = element_text(face = "plain", color = "black", size = 14),
axis.title.x=element_text(face="bold",colour="black",size = 14),
axis.title.y=element_text(face="bold",colour="black",size = 14),
strip.background = element_rect(colour = "black", fill = "white",size=1),
strip.text.x = element_text(size=14, angle=0, face = "plain"),
strip.text.y = element_text(size=14, face="plain"),
legend.title = element_text(colour="black", size=14, face="bold"),
axis.text = element_text(face = "bold", vjust = 0.5, size = 14))

#ggsave("D:/R/Pictures/Node/Iversen_9SowingDateSD2Waterirrnode.png", width=8, height=3, dpi=500)
obsNode1<-obsNode%>%
#dplyr::filter(Ture!="No")%>%
dplyr::filter(Collection=="2000_2002")%>%
dplyr::filter(Name=="Iversen_9SowingDateSD3Waterirr")
obsNode1$Rotation2<- factor(obsNode1$Rotation2, levels=c("S1", "R2", "R3", "R4", "R5","R6"))
obsNode1%>%
ggplot(aes(x=Tt_beta_sum, y=Observed), colour=factor(Name))+geom_point(size=2)+theme_bw()+xlab("Thermal time (°Cd)")+ylab("Node number")+ggtitle("E2ILLS3(Iversen_9SowingDateSD3Waterirr)")+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="blue")+
facet_grid(GrowthSeason2~Rotation2)+theme(axis.title.x=element_text(face="bold",colour="black",size = 12))+
theme(axis.title.y=element_text(face="bold",colour="black",size = 14))+
#remove grid lines
theme(
panel.spacing=unit(.01, "lines"),
panel.border = element_rect(colour = "black",size=1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black",size = 1),
axis.text.x = element_text(face = "plain", color = "black", size = 14, vjust=0.5, hjust = 1),
axis.text.y = element_text(face = "plain", color = "black", size = 14),
axis.title.x=element_text(face="bold",colour="black",size = 14),
axis.title.y=element_text(face="bold",colour="black",size = 14),
strip.background = element_rect(colour = "black", fill = "white",size=1),
strip.text.x = element_text(size=14, angle=0, face = "plain"),
strip.text.y = element_text(size=14, face="plain"),
legend.title = element_text(colour="black", size=14, face="bold"),
axis.text = element_text(face = "bold", vjust = 0.5, size = 14))

#ggsave("D:/R/Pictures/Node/Iversen_9SowingDateSD3Waterirrnode.png", width=8, height=3, dpi=500)
obsNode1<-obsNode%>%
#dplyr::filter(Ture!="No")%>%
dplyr::filter(Collection=="2000_2002")%>%
dplyr::filter(Name=="Iversen_9SowingDateSD4Waterirr")
obsNode1$Rotation2<- factor(obsNode1$Rotation2, levels=c("S1", "R2", "R3", "R4", "R5","R6"))
obsNode1%>%
ggplot(aes(x=Tt_beta_sum, y=Observed), colour=factor(Name))+geom_point(size=2)+theme_bw()+xlab("Thermal time (°Cd)")+ylab("Node number")+ggtitle("E2ILLS4(Iversen_9SowingDateSD4Waterirr)")+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="blue")+
facet_grid(GrowthSeason2~Rotation2)+theme(axis.title.x=element_text(face="bold",colour="black",size = 12))+
#remove grid lines
theme(
panel.spacing=unit(.01, "lines"),
panel.border = element_rect(colour = "black",size=1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black",size = 1),
axis.text.x = element_text(face = "plain", color = "black", size = 14, vjust=0.5, hjust = 1),
axis.text.y = element_text(face = "plain", color = "black", size = 14),
axis.title.x=element_text(face="bold",colour="black",size = 14),
axis.title.y=element_text(face="bold",colour="black",size = 14),
strip.background = element_rect(colour = "black", fill = "white",size=1),
strip.text.x = element_text(size=14, angle=0, face = "plain"),
strip.text.y = element_text(size=14, face="plain"),
legend.title = element_text(colour="black", size=14, face="bold"),
axis.text = element_text(face = "bold", vjust = 0.5, size = 14))

#ggsave("D:/R/Pictures/Node/Iversen_9SowingDateSD4Waterirrnode.png", width=8, height=3, dpi=500)
obsNode4<-obsNode%>%
#dplyr::filter(Ture!="No")%>%
dplyr::filter(Name=="Iversen_91DefoliationLL")
obsNode4$Rotation2<- factor(obsNode4$Rotation2, levels=c("R1", "R2", "R3", "R4", "R5","R6","R7"))
obsNode4%>%
ggplot(aes(x=Tt_beta_sum, y=Observed), colour=factor(Name))+geom_point(size=2)+theme_bw()+xlab("Thermal time (°Cd)")+ylab("Node number")+
#ggtitle("E3ILL(Iversen_91DefoliationLL)")+
scale_x_continuous(breaks = seq(0, 550, by =200), limits=c(0,450))+
scale_y_continuous(breaks = seq(0, 18, by =6), limits=c(0,16))+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="blue")+
facet_grid(GrowthSeason2~Rotation2)+
mytheme1

#ggsave("D:/R/Pictures/Node/Iversen_91DefoliationLLnode.png", width=8, height=5, dpi=500)
ggsave("D:/R/Pictures/Poster/nodenumberE3.png", width=8, height=4, dpi=500)
obsNodeLL<-obsNode%>%
dplyr::filter(Name=="Iversen_121DefoliationLLFDFD5")
obsNodeLL$Rotation2<- factor(obsNodeLL$Rotation2, levels=c("S1", "R2", "R3", "R4", "R5","R6","R7"))
obsNodeLL%>%
ggplot(aes(x=Tt_beta_sum, y=Observed), colour=factor(Name))+geom_point(size=2)+theme_bw()+xlab("Thermal time (°Cd)")+scale_x_continuous(limits=c(0,430))+
ylab("Node number")+ggtitle("E5ILLF5(Iverson_121DefoliationLLFDFD5)")+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="blue")+
scale_x_continuous(breaks = seq(0, 550, by =200), limits=c(0,450))+
scale_y_continuous(breaks = seq(0, 18, by =6), limits=c(0,16))+
facet_grid(GrowthSeason2~Rotation2)+
mytheme1
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.

# ggsave("D:/R/Pictures/Node/Iversen_121DefoliationLLFDFD5node.png", width=8, height=6, dpi=500)
R squared and phyllo calculation for each rotation
TTWES1
Tb evaluation
#obsef1%>%
# dplyr::filter(Ture!="No")
# statWE1<-ObsH%>%
# filter(Variable == "NodeNumber") %>%
# filter(Water=="irr")%>%
# filter(Defoliation=="LL")%>%
# mutate(GrowthSeason=factor(GrowthSeason))%>%
# group_by(GrowthSeason,Collection) %>%
uniTb <- unique(ObsH$Tb)
PhyBeta.all <- data.frame()
for(i in 1:length(uniTb)){
ObsH1 <- ObsH %>%
filter(Tb==uniTb[i])
ObsH.sub <- ObsH1 %>%
group_by(Name,GrowthSeason.x,Rotation.x,Collection,Tmean,Ppm,Tb,ID,ExperimentID) %>%
do(mod.beta = lm(Tt_beta_sum~Observed,data=.))%>%
mutate(R2WE = summary(mod.beta)$r.squared)%>%
mutate(PhylloWE = summary(mod.beta)$coeff[2])%>%
dplyr::select(-mod.beta)
PhyBeta.all <- rbind(PhyBeta.all, ObsH.sub)
}
PhyBeta.all
write.csv(PhyBeta.all,"D:/R/PhyllochronData/PhyBeta.all.csv", row.names = FALSE)
uniTb <- unique(ObsH$Tb)
Phybroken.all <- data.frame()
for(i in 1:length(uniTb)){
ObsH1 <- ObsH %>%
filter(Tb==uniTb[i])
ObsH.sub <- ObsH1 %>%
group_by(Name,GrowthSeason.x,Rotation.x,Collection,Tmean,Ppm,Tb,ID,ExperimentID) %>%
do(mod.broken = lm(Tt_broken_sum~Observed,data=.))%>%
#do(mod.fick = lm(Tt_fick_sum~Observed,data=.))%>%
mutate(R2Br = summary(mod.broken)$r.squared)%>%
mutate(PhylloBr = summary(mod.broken)$coeff[2])%>%
mutate(P=anova(mod.broken)$'Pr(>F)'[1])%>%
mutate(intcp= summary(mod.broken)$coeff[1])%>%
dplyr::select(-mod.broken)
Phybroken.all <- rbind(Phybroken.all, ObsH.sub)
}
ANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliable
Phybroken.all
write.csv(Phybroken.all,"D:/R/PhyllochronData/Phybroken.all.csv", row.names = FALSE)
uniTb <- unique(ObsH$Tb)
Phyfick.all <- data.frame()
for(i in 1:length(uniTb)){
ObsH1 <- ObsH %>%
filter(Tb==uniTb[i])
ObsH.sub <- ObsH1 %>%
group_by(Name,GrowthSeason.x,Rotation.x,Collection,Tmean,Ppm,Tb,ID,ExperimentID) %>%
do(mod.fick = lm(Tt_fick_sum~Observed,data=.))%>%
mutate(R2fi = summary(mod.fick)$r.squared)%>%
mutate(Phyllofick = summary(mod.fick)$coeff[2])%>%
dplyr::select(-mod.fick)
Phyfick.all <- rbind(Phyfick.all, ObsH.sub)
}
Phyfick.all
write.csv(Phyfick.all,"D:/R/PhyllochronData/Phyfick.all.csv", row.names = FALSE)
Combine the Phyllo data together
multmerge = function(mypath){
filenames=list.files(path=mypath, full.names=TRUE)
datalist = lapply(filenames, function(x){read.csv(file=x,header=T)})
Reduce(function(x,y) {merge(x,y)}, datalist)}
mergephy=multmerge("D:/R/PhyllochronData")
mergephy
mergeP<-mergephy%>%
dplyr::select(Name,GrowthSeason.x,Rotation.x,Collection,Tmean, Ppm,Tb, PhylloWE,PhylloBr,Phyllofick,ID,ExperimentID) %>%
tidyr::gather("Variable","Phyllo",PhylloWE:Phyllofick)%>%
mutate(PhylloTb=as.factor(paste0(Variable,Tb)))%>%
mutate(GrowthRotation=as.factor(paste0(GrowthSeason.x,Rotation.x)))
unique(mergeP)
mergeP$Names[mergeP$Name=="Iversen_8Waterirr" ] <-"I8irr"
mergeP$Names[mergeP$Name=="Iversen_91DefoliationLL"] <-"I9LL"
mergeP$Names[mergeP$Name=="Iversen_9SowingDateSD1Waterirr"]<-"I9SD1irr"
mergeP$Names[mergeP$Name=="Iversen_9SowingDateSD2Waterirr"]<-"I9SD2irr"
mergeP$Names[mergeP$Name=="Iversen_9SowingDateSD3Waterirr"]<-"I9SD3irr"
mergeP$Names[mergeP$Name=="Iversen_9SowingDateSD4Waterirr"]<-"I9SD4irr"
mergeP$Names[mergeP$Name=="Iversen_121DefoliationLLFDFD5"]<-"I12DF5"
mergeP
Regression coefficient
mergeP%>%
ggplot(aes(x=Tmean, y=Phyllo, colour=factor(Names)))+geom_point(size=2)+theme_bw()+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="darkgrey")+xlab("Mean air temperature (°C)")+ylab("Phyllochron (°Cd/Leaf)")+
facet_wrap(~PhylloTb,ncol = 2)+
theme(axis.title.x=element_text(face="bold",colour="black",size = 12))+
theme(axis.title.y=element_text(face="bold",colour="black",size = 12))

NA
uniPhy <- unique(mergeP$PhylloTb)
Slope.df<-data.frame()
for(i in 1:length(uniPhy) ){
mergeP.sub <- mergeP %>%
filter(PhylloTb==uniPhy[i])%>%
group_by(PhylloTb) %>%
do(modPhy = lm(Tmean~Phyllo,data=.))%>%
mutate(R2 = summary(modPhy)$r.squared)%>%
mutate(slope = summary(modPhy)$coeff[2])%>%
mutate(P=anova(modPhy)$'Pr(>F)'[1])%>%
dplyr::select(-modPhy)
Slope.df <- rbind(Slope.df,mergeP.sub)
}
Slope.df
CV coeffecient of variation
mergeP
mergePcv<-mergeP%>%group_by(Collection, Variable)%>%
mutate(meanPhyllo=mean(Phyllo))%>%
mutate(SDPhyllo=sd(Phyllo))%>%
mutate(CVPhyllo=SDPhyllo/meanPhyllo)
mergePcv
mergePcv1<-mergePcv%>%group_by(Variable)%>%
mutate(CVmean=mean(CVPhyllo))
mergePcv%>%
ggplot(aes(x=PhylloTb,y=CVPhyllo,color=factor(Collection)))+geom_point(size=2)+theme_bw()

mergePcv1%>%
ggplot(aes(x=PhylloTb,y=CVmean))+geom_point(size=2)+theme_bw()

mergePcv1
x-intercept method
LAR2<-ObsH%>%
group_by(Name,GrowthSeason.x,Rotation.x,Collection,Tmean,Ppm,GrowthRotation,ExperimentID,ID) %>%
do(mod = lm(Observed~Interval,data=.)) %>%
mutate(slope = summary(mod)$coeff[2]) %>%
mutate(R2 = summary(mod)$r.squared)%>%
mutate(P=anova(mod)$'Pr(>F)'[1])%>%
mutate(intcp= summary(mod)$coeff[1])%>%
dplyr::select(-mod)
essentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableANOVA F-tests on an essentially perfect fit are unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliable
LAR.ana<- ObsH%>%
group_by(Collection,ExperimentID) %>%
do(mod = lm(Observed~Interval,data=.)) %>%
mutate(slope = summary(mod)$coeff[2]) %>%
mutate(R2 = summary(mod)$r.squared)%>%
mutate(P=anova(mod)$'Pr(>F)'[1])%>%
mutate(intcp= summary(mod)$coeff[1])%>%
dplyr::select(-mod)
library(plyr)
--------------------------------------------------------------------------------------------------------------
You have loaded plyr after dplyr - this is likely to cause problems.
If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
library(plyr); library(dplyr)
--------------------------------------------------------------------------------------------------------------
Attaching package: <U+393C><U+3E31>plyr<U+393C><U+3E32>
The following object is masked from <U+393C><U+3E31>package:lubridate<U+393C><U+3E32>:
here
The following objects are masked from <U+393C><U+3E31>package:dplyr<U+393C><U+3E32>:
arrange, count, desc, failwith, id, mutate, rename, summarise, summarize
LAR.NEW<-LAR2%>%
dplyr::filter(Rotation.x!="6"|Collection!="1997_2001")%>%
mutate(NAR=slope)%>%
dplyr::filter(Collection!="2014_2019")%>%
dplyr::filter(Collection!="2010_2012")%>%
dplyr::select(Name, Collection, GrowthRotation, NAR,Tmean,Ppm,ExperimentID,ID)
#dplyr::filter(Collection==C("2000_2002","1997_2001","2014_2018","2002_2004"))
LAR.NEW$Collection
[1] 2014_2018 2014_2018 2014_2018 2014_2018 2014_2018 2014_2018 2014_2018 2014_2018 2014_2018 2014_2018
[11] 2014_2018 2014_2018 2014_2018 2014_2018 2014_2018 2014_2018 2014_2018 2014_2018 2014_2018 2014_2018
[21] 1997_2001 1997_2001 1997_2001 1997_2001 1997_2001 1997_2001 1997_2001 1997_2001 1997_2001 1997_2001
[31] 1997_2001 1997_2001 1997_2001 1997_2001 1997_2001 1997_2001 1997_2001 1997_2001 1997_2001 2002_2004
[41] 2002_2004 2002_2004 2002_2004 2002_2004 2002_2004 2002_2004 2002_2004 2002_2004 2002_2004 2002_2004
[51] 2002_2004 2002_2004 2002_2004 2002_2004 2000_2002 2000_2002 2000_2002 2000_2002 2000_2002 2000_2002
[61] 2000_2002 2000_2002 2000_2002 2000_2002 2000_2002 2000_2002 2000_2002 2000_2002 2000_2002 2000_2002
[71] 2000_2002
Levels: 1997_2001 2000_2002 2002_2004 2010_2012 2014_2018
lm_eqn <- function(LAR.NEW){
m <- lm(NAR ~ Tmean, LAR.NEW);
eq <- substitute(italic(y) == Tmean + NAR %.% italic(Tmean)*","~~italic(R)^2~"="~r2,
list(Tmean = format(coef(m)[1], digits = 2),
NAR = format(coef(m)[2], digits = 2),
r2 = format(summary(m)$r.squared, digits = 3)))
as.character(as.expression(eq));
}
eqns <- ddply(LAR.NEW,.(ExperimentID),lm_eqn)
#df2 <- data.frame(eq = unclass(eqns), Collection = as.numeric(names(eqns)))
a<-ggplot(LAR.NEW, aes(x=Tmean, y=NAR))+
geom_point()+theme_bw()+xlab("Mean air temperature (°C)")+
geom_text(data = eqns, aes(x = 13, y = 0.48, label = V1), size=4.7,
color = 'black', parse = TRUE)+
ylab(bquote(bold('Node appearance rate ('*node~day^-1*')')))+
scale_x_continuous(limits=c(5,20))+
facet_wrap(~ExperimentID)+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="darkgrey")+
#remove grid lines
theme(
panel.spacing=unit(.01, "lines"),
panel.border = element_rect(colour = "black",size=1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black",size = 1),
axis.text.x = element_text(face = "plain", color = "black", size = 14),
axis.text.y = element_text(face = "plain", color = "black", size = 14),
axis.title.x=element_text(face="bold",colour="black",size = 14),
axis.title.y=element_text(face="bold",colour="black",size = 14),
strip.background = element_rect(colour = "black", fill = "white",size=1),
strip.text.x = element_text(size=14, angle=0, face = "plain"),
strip.text.y = element_text(size=14, face="plain"),
legend.title = element_text(colour="black", size=14, face="bold"))
#ggsave("D:/R/Pictures/Node/Node apparence rate.png", width=8, height=6, dpi=500)
a

detach(package:plyr)
LAR2
#dplyr::filter(Rotation!="6"|Collection!="1997_2001")
LAR2.lm=lm(slope~Tmean,data=LAR2)
summary(LAR2.lm)
Call:
lm(formula = slope ~ Tmean, data = LAR2)
Residuals:
Min 1Q Median 3Q Max
-0.142755 -0.060941 -0.007349 0.056628 0.171460
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.001896 0.035007 0.054 0.957
Tmean 0.018709 0.002579 7.254 3.51e-10 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.0702 on 73 degrees of freedom
Multiple R-squared: 0.4189, Adjusted R-squared: 0.4109
F-statistic: 52.62 on 1 and 73 DF, p-value: 3.514e-10
predict(LAR2.lm, LAR2, interval="predict")
fit lwr upr
1 0.2893523 0.1480724703 0.4306321
2 0.3120969 0.1701889979 0.4540047
3 0.2619888 0.1211005062 0.4028771
4 0.1869465 0.0450782027 0.3288149
5 0.2000531 0.0585718438 0.3415344
6 0.2513464 0.1105023104 0.3921906
7 0.2765514 0.1355044768 0.4175983
8 0.3349125 0.1921023944 0.4777226
9 0.2993657 0.1578430814 0.4408884
10 0.2525481 0.1117019893 0.3933941
11 0.1935086 0.0518454158 0.3351719
12 0.2392637 0.0983960731 0.3801313
13 0.2969517 0.1554924451 0.4384110
14 0.3221620 0.1798894771 0.4644346
15 0.2352880 0.0943956278 0.3761805
16 0.1333112 -0.0110690730 0.2776915
17 0.1533606 0.0100914352 0.2966298
18 0.2095842 0.0683274321 0.3508410
19 0.2702247 0.1292606681 0.4111888
20 0.3318085 0.1891370263 0.4744800
21 0.2495323 0.1086895917 0.3903749
22 0.2923774 0.1510298770 0.4337250
23 0.3336207 0.1908688777 0.4763725
24 0.3634814 0.2191650559 0.5077977
25 0.2450865 0.1042399689 0.3859330
26 0.1535398 0.0102796064 0.2967999
27 0.2354077 0.0945161478 0.3762992
28 0.3309772 0.1883419635 0.4736124
29 0.3301017 0.1875042479 0.4726991
30 0.2995955 0.1580666437 0.4411244
31 0.1463030 0.0026657522 0.2899402
32 0.2506783 0.1098348849 0.3915217
33 0.2480100 0.1071672463 0.3888528
34 0.2729272 0.1319303996 0.4139241
35 0.3034658 0.1618283601 0.4451032
36 0.2234391 0.0824225637 0.3644557
37 0.1600318 0.0170872149 0.3029764
38 0.2139924 0.0728231885 0.3551617
39 0.2661918 0.1252694018 0.4071142
40 0.2899563 0.1486633616 0.4312493
41 0.3021530 0.1605532780 0.4437527
42 0.2606499 0.1197705610 0.4015293
43 0.1540197 0.0107836082 0.2972558
44 0.1506963 0.0072911582 0.2941014
45 0.2072025 0.0658941893 0.3485109
46 0.2717034 0.1307219139 0.4126849
47 0.3040429 0.1623886825 0.4456972
48 0.2951563 0.1537421606 0.4365704
49 0.2200926 0.0790273555 0.3611578
50 0.1848582 0.0429198350 0.3267965
51 0.1446357 0.0009078732 0.2883635
52 0.2254167 0.0844260563 0.3664073
53 0.2742309 0.1332168195 0.4152449
54 0.3343193 0.1915360585 0.4771025
55 0.2843987 0.1432193579 0.4255780
56 0.2192580 0.0781797125 0.3603363
57 0.1816873 0.0396382547 0.3237363
58 0.1367467 -0.0074288436 0.2809223
59 0.2660152 0.1250944531 0.4069360
60 0.3071611 0.1654126789 0.4489095
61 0.2631297 0.1222331118 0.4040263
62 0.1518678 0.0085229389 0.2952128
63 0.1462936 0.0026559031 0.2899313
64 0.2394569 0.0985902525 0.3803235
65 0.2851066 0.1439137000 0.4262995
66 0.2989340 0.1574229054 0.4404451
67 0.2802534 0.1391481144 0.4213587
68 0.1997933 0.0583052053 0.3412813
69 0.2834632 0.1423014254 0.4246251
70 0.2780814 0.1370112789 0.4191516
71 0.1516538 0.0082979287 0.2950096
72 0.3046530 0.1629807368 0.4463253
73 0.2631297 0.1222331118 0.4040263
74 0.2977827 0.1563019543 0.4392634
75 0.2422188 0.1013641807 0.3830734
# LARs<-LAR1%>%
# dplyr::filter(Collection=="2014_2018")
#
# LAR.lm = lm(Observed ~ TTS2, data=LARs)
# LAR.res = resid(LAR.lm)
#
#
# plot(LARs$Clock.Today, LAR.res, ylab="Residuals", xlab="Date")
# abline(0, 0)
load Rotation and Growth season for poster
library(plyr)
phyll <- "D:\\R\\"
StartGrazing <- read.table(paste0(phyll, "ExperimentList.txt"),
header = TRUE)
StartGrazing1<-StartGrazing %>%
mutate(GrowthRotation= as.factor(paste0(GrowthSeason,Rotation)))
PhyPp<- merge(StartGrazing1,mergeP,by=c("Name","Collection","GrowthRotation"))
lm_eqn1 <- function(PhyPp){
m <- lm(Phyllo~Ppm , PhyPp);
eq <- substitute(italic(y) == Ppm + Phyllo %.% italic(Ppm)*","~~italic(R)^2~"="~r2,
list(Ppm = format(coef(m)[1], digits = 2),
Phyllo = format(coef(m)[2], digits = 2),
r2 = format(summary(m)$r.squared, digits = 3)))
as.character(as.expression(eq));
}
eqs <- ddply(PhyPp,.(Trend,Stage),lm_eqn1)
#df2 <- data.frame(eq = unclass(eqns), Collection = as.numeric(names(eqns)))
#ylab(bquote(bold('LEAR ('*m^2~m^-2~'°Cd'^-1*')')))
PhyPp
mergeP
PhyPp%>%
#dplyr::filter(Rotation!="1")%>%
#dplyr::filter(Rotation!="7")%>%
#dplyr::filter(Name!="Iversen_8Waterirr"|GrowthSeason!="3")%>%
#dplyr::filter(Stage!="Seedling")%>%
dplyr::filter(PhylloTb=="PhylloBr1")%>%
dplyr::filter(Collection!="2010_2012")%>%
ggplot(aes(x=Ppm, y=Phyllo,label=GrowthRotation,color=ID))+geom_text()+theme_bw()+xlab("Mean photoperiod (h)")+ylab(bquote(bold('Phyllochron ('*'°Cd'~'main node'^-1*')')))+
geom_text(data = eqs, aes(x =13, y = 78, label = V1),
color = 'black', parse = TRUE)+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="darkgrey")+
facet_grid(Trend~Stage)+
#facet_wrap(~Stage,ncol = 2)+
#geom_point(size=2)+
scale_y_continuous(breaks = seq(0, 70, by =20), limits=c(0,78))+
mytheme3+theme(legend.title = element_blank())
#ggsave("D:/R/Pictures/Node/phyll.png", width=8, height=6, dpi=500)
detach(package:plyr)
PhyPpD<-PhyPp%>%
dplyr::filter(Stage=="Regrowth")%>%
dplyr::filter(Trend=="Dec")
mod<-lm(PhyPpD$Phyllo~PhyPpD$Ppm)
summary(mod)
Call:
lm(formula = PhyPpD$Phyllo ~ PhyPpD$Ppm)
Residuals:
Min 1Q Median 3Q Max
-35.075 -8.259 0.246 7.268 46.956
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 49.4449 3.3782 14.636 < 2e-16 ***
PhyPpD$Ppm -0.9483 0.2477 -3.828 0.000142 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 13.4 on 643 degrees of freedom
Multiple R-squared: 0.02229, Adjusted R-squared: 0.02077
F-statistic: 14.66 on 1 and 643 DF, p-value: 0.0001416
PhyPpI<-PhyPp%>%
dplyr::filter(Stage=="Regrowth")%>%
dplyr::filter(Trend!="Dec")
mod<-lm(PhyPpI$Phyllo~PhyPpI$Ppm)
summary(mod)
Call:
lm(formula = PhyPpI$Phyllo ~ PhyPpI$Ppm)
Residuals:
Min 1Q Median 3Q Max
-24.205 -9.945 -0.083 7.226 44.098
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 22.8304 4.5053 5.067 6.15e-07 ***
PhyPpI$Ppm 0.2081 0.3201 0.650 0.516
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 12.51 on 403 degrees of freedom
Multiple R-squared: 0.001048, Adjusted R-squared: -0.001431
F-statistic: 0.4228 on 1 and 403 DF, p-value: 0.5159
Define stats function
- Using Gauch et al. 2003 (Model evaluation by comparison of model-based predictions and measured values. Agron. J. 95, 1442-1446)
Test stats functions used
s <- c(4231.972,3935.604,3779.652,3627.687,3363.499,3230.566,2868.114,2868.827)
m <- c(4987.66,5636.09,4754.06,4114.53,4141.72,3704.06,5142.19,4762.03)
x <- gauchStats(s,m)
tempDf <- data.frame(statName=c("SB","NU","LC","r_MSD","R2"), statValue=x)
# kable(tempDf, digits= 2)
tempDf2 <- data.frame(Predicted=s, Observed=m)
x <- tempDf2 %>%
summarise(
n = n(),
r2 = gauchStats(Predicted,Observed)[5],
# rmse = round(rmse(Predicted,Observed),0),
r_rmse = round(rmse(Predicted,Observed)/mean(Observed)*100,1),
nse = round(NSE(Predicted,Observed),1),
sb = gauchStats(Predicted,Observed)[1],
nu = gauchStats(Predicted,Observed)[2],
lc = gauchStats(Predicted,Observed)[3]
) %>%
t()
df <- data.frame(stat = row.names(x),statvalue = x[,1])
df %>%
kable(format = "markdown")
| n |
n |
8.0 |
| r2 |
r2 |
7.1 |
| r_rmse |
r_rmse |
28.7 |
| nse |
nse |
-4.1 |
| sb |
sb |
76.5 |
| nu |
nu |
5.2 |
| lc |
lc |
18.2 |
Load simulated database
create function to read data (Justin’s script)
Time series
obs Vs Pre for each experiment
1997-2001
obsNode1<-obsA%>%
dplyr::filter(Collection=="1997_2001")%>%
dplyr::filter(Variable=="NodeNumber")%>%
dplyr::filter(Name=="Iversen_8Waterirr")%>%
dplyr::filter(Clock.Today>"1997-08-01")%>%
dplyr::filter(Clock.Today<"2001-08-01")
simD1<-simD%>%
mutate(Clock.Today = ymd_hms(Clock.Today))%>%
dplyr::filter(Clock.Today>"1997-08-01")%>%
dplyr::filter(Clock.Today<"2001-08-01")%>%
dplyr::filter(Variable=="NodeNumber")%>%
dplyr::filter(Name=="Iversen_8Waterirr")
str(simD1)
'data.frame': 1460 obs. of 4 variables:
$ Name : Factor w/ 103 levels "AshleyDeneSowingDateSD1",..: 49 49 49 49 49 49 49 49 49 49 ...
$ Clock.Today: POSIXct, format: "1998-08-03 12:00:00" "1998-05-11 12:00:00" "1997-09-03 12:00:00" "1997-08-26 12:00:00" ...
$ Variable : Factor w/ 8 levels "Height","LAI",..: 4 4 4 4 4 4 4 4 4 4 ...
$ Predicted : num 3.14 12.13 7.55 6.54 6.08 ...
simD1%>%
ggplot(aes(x=Clock.Today,y=Predicted))+geom_line(size=1)+theme_bw()+
facet_wrap(~ID,ncol = 2)+
geom_point(data=obsNode1, aes(x=Clock.Today1, y=Observed),colour="green",size=3)+
theme(legend.title=element_blank(),legend.position = "blank")+xlab("Date")+ylab("Node number")+
#remove grid lines
theme(
panel.spacing=unit(.01, "lines"),
panel.border = element_rect(colour = "black",size=1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black",size = 1),
axis.text.x = element_text(face = "plain", color = "black", size = 14, vjust=0.5, hjust = 1),
axis.text.y = element_text(face = "plain", color = "black", size = 14),
axis.title.x=element_text(face="bold",colour="black",size = 14),
axis.title.y=element_text(face="bold",colour="black",size = 14),
strip.background = element_rect(colour = "black", fill = "white",size=1),
strip.text.x = element_text(size=14, angle=0, face = "plain"),
strip.text.y = element_text(size=14, face="plain"),
legend.title = element_text(colour="black", size=14, face="bold"),
axis.text = element_text(face = "bold", vjust = 0.5, size = 14))+
annotate("text", x=ymd_hms("1999-10-24 12:00:00"), y=17, size = 5, label ="paste(R_RMSD == 21.8,'%')", parse=T)

#ggsave("D:/R/Pictures/Node/Iversen_8Waterirrnodenumber.png", width=8, height=4, dpi=500)
2002-2004
obsNode2<-obsNode%>%
dplyr::filter(Collection=="2002_2004")%>%
dplyr::filter(Variable=="NodeNumber")%>%
dplyr::filter(Name=="Iversen_91DefoliationLL")
simD2<-simD%>%
mutate(Clock.Today = ymd_hms(Clock.Today))%>%
dplyr::filter(Clock.Today>"2002-06-01")%>%
dplyr::filter(Variable=="NodeNumber")%>%
dplyr::filter(Name=="Iversen_91DefoliationLL")
str(simD2)
'data.frame': 884 obs. of 4 variables:
$ Name : Factor w/ 103 levels "AshleyDeneSowingDateSD1",..: 50 50 50 50 50 50 50 50 50 50 ...
$ Clock.Today: POSIXct, format: "2004-09-22 12:00:00" "2003-03-21 12:00:00" "2003-03-22 12:00:00" "2003-03-23 12:00:00" ...
$ Variable : Factor w/ 8 levels "Height","LAI",..: 4 4 4 4 4 4 4 4 4 4 ...
$ Predicted : num 9.205 11.556 11.835 0.274 0.738 ...
simD2%>%
ggplot(aes(x=Clock.Today,y=Predicted))+geom_line(size=1)+theme_bw()+
#facet_wrap(~ID,ncol = 1)+
geom_point(data=obsNode2, aes(x=Clock.Today1, y=Observed),colour="blue",size=3)+
theme(legend.title=element_blank(),legend.position = "blank")+xlab("Date")+ylab("Node number")+
#remove grid lines
theme(
panel.spacing=unit(.01, "lines"),
panel.border = element_rect(colour = "black",size=1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black",size = 1),
axis.text.x = element_text(face = "plain", color = "black", size = 14, vjust=0.5, hjust = 1),
axis.text.y = element_text(face = "plain", color = "black", size = 14),
axis.title.x=element_text(face="bold",colour="black",size = 14),
axis.title.y=element_text(face="bold",colour="black",size = 14),
strip.background = element_rect(colour = "black", fill = "white",size=1),
strip.text.x = element_text(size=14, angle=0, face = "plain"),
strip.text.y = element_text(size=14, face="plain"),
legend.title = element_text(colour="black", size=14, face="bold"),
axis.text = element_text(face = "bold", vjust = 0.5, size = 14))+
annotate("text", x=ymd_hms("2003-07-24 12:00:00"), y=17, size = 5, label ="paste(R_RMSD == 21.9,'%')", parse=T)

#ggsave("D:/R/Pictures/Node/Iversen_91DefoliationLLnodenumber.png", width=8, height=4, dpi=500)
ggsave("D:/R/Pictures/Poster/E3.png", width=8, height=4, dpi=500)
2000-2002
obsNode3<-obsNode%>%
dplyr::filter(Collection=="2000_2002")%>%
dplyr::filter(Variable=="NodeNumber")
obsNode3
simD3a<-simD%>%
mutate(Clock.Today = ymd_hms(Clock.Today))%>%
dplyr::filter(Clock.Today>"2000-10-24 12:00:00")%>%
dplyr::filter(Clock.Today<"2002-07-01 12:00:00")%>%
dplyr::filter(Name==c("Iversen_9SowingDateSD1Waterirr","Iversen_9SowingDateSD2Waterirr","Iversen_9SowingDateSD3Waterirr","Iversen_9SowingDateSD4Waterirr"))%>%
dplyr::filter(Variable=="NodeNumber")
DF<-data.frame(Name=c("Iversen_9SowingDateSD1Waterirr","Iversen_9SowingDateSD2Waterirr","Iversen_9SowingDateSD3Waterirr","Iversen_9SowingDateSD4Waterirr"),ID= c("E2ILLS1","E2ILLS2","E2ILLS3","E2ILLS4"))
simD3<-merge(DF,simD3a, by=c("Name"))
G<-simD3%>%
ggplot(aes(x=Clock.Today,y=Predicted))+geom_line(size=1)+theme_bw()+
geom_point(data=obsNode3, aes(x=Clock.Today1, y=Observed),colour="green",size=3)+
facet_wrap(~ID,ncol = 2)+
theme(legend.title=element_blank(),legend.position = "blank")+xlab("Date")+ylab("Node number")+
theme(
panel.spacing=unit(.01, "lines"),
panel.border = element_rect(colour = "black",size=1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black",size = 1),
axis.text.x = element_text(face = "plain", color = "black", size = 14, vjust=0.5, hjust = 1),
axis.text.y = element_text(face = "plain", color = "black", size = 14),
axis.title.x=element_text(face="bold",colour="black",size = 14),
axis.title.y=element_text(face="bold",colour="black",size = 14),
strip.background = element_rect(colour = "black", fill = "white",size=1),
strip.text.x = element_text(size=14, angle=0, face = "plain"),
strip.text.y = element_text(size=14, face="plain"),
legend.title = element_text(colour="black", size=14, face="bold"),
axis.text = element_text(face = "bold", vjust = 0.5, size = 14))
dat_text1 <- data.frame(
label = c("R_RMSE=27.7%", "R_RMSE=28%", "R_RMSE=21.8%","R_RMSE=24.5%"),
ID= c("E2ILLS1","E2ILLS2","E2ILLS3","E2ILLS4"),
x= ymd_hms("2001-03-24 12:00:00", "2001-03-24 12:00:00","2001-03-24 12:00:00","2001-03-24 12:00:00"),
y=c(17,17,17,17))
G+geom_text(data=dat_text1, mapping = aes(x=x,y=y, label = label),hjust = -0.1,vjust = -1,size=5)

#ggsave("D:/R/Pictures/Node/Iversen_9SowingDatenodenumber.png", width=8, height=8, dpi=500)
2014-2018
obsNode4<-obsNode%>%
dplyr::filter(Collection=="2014_2018")%>%
dplyr::filter(Variable=="NodeNumber")%>%
dplyr::filter(Name=="Iversen_121DefoliationLLFDFD5")
simD4a<-simD%>%
mutate(Clock.Today = ymd_hms(Clock.Today))%>%
dplyr::filter(Variable=="NodeNumber")%>%
dplyr::filter(Name=="Iversen_121DefoliationLLFDFD5")%>%
dplyr::filter(Clock.Today<"2015-01-06")
simD4b<-simD%>%
mutate(Clock.Today = ymd_hms(Clock.Today))%>%
dplyr::filter(Variable=="NodeNumber")%>%
dplyr::filter(Name=="Iversen_121DefoliationLLFDFD5")%>%
dplyr::filter(Clock.Today>"2015-01-30")
simD4<-rbind(simD4a,simD4b)
str(simD4)
'data.frame': 1158 obs. of 4 variables:
$ Name : Factor w/ 103 levels "AshleyDeneSowingDateSD1",..: 20 20 20 20 20 20 20 20 20 20 ...
$ Clock.Today: POSIXct, format: "2014-10-08 12:00:00" "2014-10-09 12:00:00" "2014-10-10 12:00:00" "2014-10-11 12:00:00" ...
$ Variable : Factor w/ 8 levels "Height","LAI",..: 4 4 4 4 4 4 4 4 4 4 ...
$ Predicted : num 0 0 0 0 0 0 0 0 0 0 ...
simD4%>%
ggplot(aes(x=Clock.Today,y=Predicted))+geom_line(size=1)+theme_bw()+
facet_wrap(~ID,ncol = 1)+
geom_point(data=obsNode4, aes(x=Clock.Today1, y=Observed),colour="green",size=3)+
theme(legend.title=element_blank(),legend.position = "blank")+xlab("Date")+ylab("Node number")+
#remove grid lines
theme(
panel.spacing=unit(.01, "lines"),
panel.border = element_rect(colour = "black",size=1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black",size = 1),
axis.text.x = element_text(face = "plain", color = "black", size = 14, vjust=0.5, hjust = 1),
axis.text.y = element_text(face = "plain", color = "black", size = 14),
axis.title.x=element_text(face="bold",colour="black",size = 14),
axis.title.y=element_text(face="bold",colour="black",size = 14),
strip.background = element_rect(colour = "black", fill = "white",size=1),
strip.text.x = element_text(size=14, angle=0, face = "plain"),
strip.text.y = element_text(size=14, face="plain"),
legend.title = element_text(colour="black", size=14, face="bold"),
axis.text = element_text(face = "bold", vjust = 0.5, size = 14))+
annotate("text", x=ymd_hms("2016-07-24 12:00:00"), y=18, size = 5, label ="paste(R_RMSD == 30,'%')", parse=T)

#ggsave("D:/R/Pictures/Node/Iversen_121DefoliationLLFDFD5nodenumber.png", width=8, height=4, dpi=500)
Statistic and Graph


2002-2004
mergedf
summary(mergedf)
Clock.Today Name Variable Collection
Min. :1997-01-28 Iversen_91DefoliationLL :586 NodeNumber :791 1997_2001: 916
1st Qu.:2001-01-06 Iversen_8Waterdry :461 Height :696 2000_2002:1020
Median :2001-09-15 Iversen_8Waterirr :455 shootbiomass:585 2002_2004: 586
Mean :2004-07-16 Iversen_121DefoliationLLFDFD5 :415 LAI :537 2010_2012: 0
3rd Qu.:2004-03-02 Iversen_9SowingDateSD1Waterirr:263 SWC :282 2014_2018: 676
Max. :2017-12-29 Iversen_9SowingDateSD1Waterdry:258 RootWt :110
(Other) :760 (Other) :197
Experiment Water Defoliation SowingDate FD Period GrowthSeason
Lincoln2000:1140 dry: 972 HH: 192 No :1502 FD10: 35 00_01 :963 Min. :1.000
Lincoln2015: 674 irr:2226 LL:3006 no : 676 FD2 : 34 01_02 :468 1st Qu.:1.000
Lincoln2001: 379 SD1 : 521 FD5 :3129 02_03 :274 Median :2.000
Lincoln2003: 286 SD2 : 186 03_04 :273 Mean :2.336
Lincoln2004: 178 SD3 : 158 15_16 :242 3rd Qu.:3.000
Lincoln1998: 168 SD4 : 155 16_17 :201 Max. :6.000
(Other) : 373 (Other): 0 (Other):777
Rotation StartDate MidDate FinishDate Interval
Min. :1.000 Min. :1996-11-01 Min. :1996-12-27 Min. :1997-02-21 Min. : 0.00
1st Qu.:1.000 1st Qu.:2000-11-14 1st Qu.:2000-12-29 1st Qu.:2001-01-24 1st Qu.: 20.00
Median :2.000 Median :2001-07-05 Median :2001-08-16 Median :2001-09-29 Median : 33.00
Mean :2.952 Mean :2004-06-08 Mean :2004-07-09 Mean :2004-08-10 Mean : 37.88
3rd Qu.:4.000 3rd Qu.:2004-02-08 3rd Qu.:2004-02-28 3rd Qu.:2004-03-19 3rd Qu.: 52.00
Max. :7.000 Max. :2017-12-04 Max. :2017-12-25 Max. :2018-01-15 Max. :122.00
VariableUnits Time Observed StdDEV ExperimentID TreatmentID
% : 0 12:00:00:3198 Min. : 0.00 Min. : 0.0000 E1: 916 ILL :1041
cm :453 1st Qu.: 5.35 1st Qu.: 0.0000 E2:1020 DLL : 461
fractio0l:575 Median : 20.03 Median : 0.3462 E3: 586 ILLF5 : 415
Fraction :216 Mean : 661.95 Mean : 94.5968 E4: 0 ILLS1 : 263
kg/ha :892 3rd Qu.: 649.67 3rd Qu.: 35.7600 E5: 676 DLLS1 : 258
m2/m2 :537 Max. :8556.38 Max. :2532.5264 IHHF5 : 192
mm :525 NA's :648 (Other): 568
ID GrowthSeason1 Rotation1 ExpUnitCode Clock.Today1
E3ILL :586 Gs_1:1044 Rt_1:967 Iversen_91DefoliationLLGs_2Rt_1: 59 Min. :1997-01-28 12:00:00
E1DLL :461 Gs_2:1127 Rt_2:646 Iversen_91DefoliationLLGs_1Rt_1: 48 1st Qu.:2001-01-06 12:00:00
E1ILL :455 Gs_3: 388 Rt_3:457 Iversen_8WaterdryGs_5Rt_1 : 42 Median :2001-09-15 12:00:00
E5ILLF5:415 Gs_4: 228 Rt_4:354 Iversen_8WaterirrGs_5Rt_1 : 42 Mean :2004-07-17 03:12:42
E2ILLS1:263 Gs_5: 369 Rt_5:354 Iversen_91DefoliationLLGs_1Rt_4: 42 3rd Qu.:2004-03-02 12:00:00
E2DLLS1:258 Gs_6: 42 Rt_6:317 Iversen_91DefoliationLLGs_1Rt_5: 42 Max. :2017-12-29 12:00:00
(Other):760 Rt_7:103 (Other) :2923
GrowthSeason2 Rotation2 Predicted
Y1(00_01): 594 R2 :646 Min. : 0.000
Y2(01_02): 426 S1 :634 1st Qu.: 5.548
Y5(00_01): 369 R3 :457 Median : 133.087
Y1(02_03): 274 R4 :354 Mean : 773.700
Y2(03_04): 273 R5 :354 3rd Qu.: 690.120
Y2(15_16): 242 R1 :333 Max. :7999.825
(Other) :1020 (Other):420
str(mergedf)
'data.frame': 3198 obs. of 30 variables:
$ Clock.Today : Date, format: "1997-01-28" "1997-01-28" "1997-02-17" "1997-02-17" ...
$ Name : Factor w/ 25 levels "Iversen_121DefoliationHHFDFD5",..: 15 16 15 16 15 16 15 16 15 16 ...
$ Variable : Factor w/ 19 levels "Branch","CrownWt",..: 13 13 6 6 13 13 13 13 13 13 ...
$ Collection : Factor w/ 5 levels "1997_2001","2000_2002",..: 1 1 1 1 1 1 1 1 1 1 ...
$ Experiment : Factor w/ 11 levels "Lincoln1997",..: 1 1 1 1 1 1 1 1 1 1 ...
$ Water : Factor w/ 2 levels "dry","irr": 1 2 1 2 1 2 1 2 1 2 ...
$ Defoliation : Factor w/ 2 levels "HH","LL": 2 2 2 2 2 2 2 2 2 2 ...
$ SowingDate : Factor w/ 12 levels "no","No","SD1",..: 2 2 2 2 2 2 2 2 2 2 ...
$ FD : Factor w/ 3 levels "FD10","FD2","FD5": 3 3 3 3 3 3 3 3 3 3 ...
$ Period : Factor w/ 16 levels "00_01","01_02",..: 13 13 13 13 13 13 13 13 14 14 ...
$ GrowthSeason : int 1 1 1 1 1 1 1 1 2 2 ...
$ Rotation : int 1 1 1 1 1 1 2 2 1 1 ...
$ StartDate : Date, format: "1996-11-01" "1996-11-01" "1996-11-01" "1996-11-01" ...
$ MidDate : Date, format: "1996-12-27" "1996-12-27" "1996-12-27" "1996-12-27" ...
$ FinishDate : Date, format: "1997-02-21" "1997-02-21" "1997-02-21" "1997-02-21" ...
$ Interval : int 88 88 108 108 112 112 103 103 51 51 ...
$ VariableUnits: Factor w/ 7 levels "%","cm","fractio0l",..: 5 5 6 6 5 5 5 5 5 5 ...
$ Time : Factor w/ 1 level "12:00:00": 1 1 1 1 1 1 1 1 1 1 ...
$ Observed : num 4613.3 4613.3 4.47 4.32 5400 ...
$ StdDEV : num 0 0 0 0 0 0 0 0 0 0 ...
$ ExperimentID : Factor w/ 5 levels "E1","E2","E3",..: 1 1 1 1 1 1 1 1 1 1 ...
$ TreatmentID : Factor w/ 20 levels "DLL","DLLS1",..: 1 13 1 13 1 13 1 13 1 13 ...
$ ID : Factor w/ 25 levels "E1DLL","E1ILL",..: 1 2 1 2 1 2 1 2 1 2 ...
$ GrowthSeason1: Factor w/ 6 levels "Gs_1","Gs_2",..: 1 1 1 1 1 1 1 1 2 2 ...
$ Rotation1 : Factor w/ 7 levels "Rt_1","Rt_2",..: 1 1 1 1 1 1 2 2 1 1 ...
$ ExpUnitCode : Factor w/ 199 levels "Iversen_8WaterdryGs_1Rt_1",..: 1 31 1 31 1 31 2 32 3 33 ...
$ Clock.Today1 : POSIXct, format: "1997-01-28 12:00:00" "1997-01-28 12:00:00" "1997-02-17 12:00:00" "1997-02-17 12:00:00" ...
$ GrowthSeason2: Factor w/ 18 levels "Y1(96_97)","Y2(97_98)",..: 1 1 1 1 1 1 1 1 2 2 ...
$ Rotation2 : Factor w/ 8 levels "R1","R2","R3",..: 1 1 1 1 1 1 2 2 1 1 ...
$ Predicted : num 69.05 69.05 4.82 4.82 2939.64 ...
mergedf %>%
dplyr::filter(Collection=="2002_2004")%>%
dplyr::filter(Variable== "NodeNumber") %>%
dplyr::filter(Water== "irr")%>%
dplyr::filter(Defoliation== "LL")%>%
ggplot(aes(x=Observed, y= Predicted,
colour= factor(Name))) +
geom_point(size=3)+theme_bw()+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="darkgrey") +
geom_abline(intercept = 0, slope = 1) +
coord_fixed(ratio = 1)+
ggtitle("Node Number")+
facet_grid(GrowthSeason~Rotation)+
theme(legend.title=element_blank(),legend.position = "blank")+xlab("Observed")+ylab("Predicted")+
theme(axis.title.x=element_text(face="bold",colour="black",size = 12))+
theme(axis.title.y=element_text(face="bold",colour="black",size = 12))

mergedf %>%
dplyr::filter(Collection=="2014_2018")%>%
dplyr::filter(Variable== "NodeNumber") %>%
dplyr::filter(Water== "irr")%>%
dplyr::filter(Defoliation== "LL")%>%
ggplot(aes(x=Observed, y= Predicted,
colour= factor(Name))) +
geom_point(size=3)+theme_bw()+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="darkgrey") +
geom_abline(intercept = 0, slope = 1) +
coord_fixed(ratio = 1)+
ggtitle("Node Number")+
facet_grid(GrowthSeason~Rotation)+
theme(legend.title=element_blank(),legend.position = "blank")+xlab("Observed")+ylab("Predicted")+
theme(axis.title.x=element_text(face="bold",colour="black",size = 12))+
theme(axis.title.y=element_text(face="bold",colour="black",size = 12))

2000-2002
mergedf
summary(mergedf)
Clock.Today Name Variable Collection
Min. :1997-01-28 Iversen_91DefoliationLL :586 NodeNumber :791 1997_2001: 916
1st Qu.:2001-01-06 Iversen_8Waterdry :461 Height :696 2000_2002:1020
Median :2001-09-15 Iversen_8Waterirr :455 shootbiomass:585 2002_2004: 586
Mean :2004-07-16 Iversen_121DefoliationLLFDFD5 :415 LAI :537 2010_2012: 0
3rd Qu.:2004-03-02 Iversen_9SowingDateSD1Waterirr:263 SWC :282 2014_2018: 676
Max. :2017-12-29 Iversen_9SowingDateSD1Waterdry:258 RootWt :110
(Other) :760 (Other) :197
Experiment Water Defoliation SowingDate FD Period GrowthSeason
Lincoln2000:1140 dry: 972 HH: 192 No :1502 FD10: 35 00_01 :963 Min. :1.000
Lincoln2015: 674 irr:2226 LL:3006 no : 676 FD2 : 34 01_02 :468 1st Qu.:1.000
Lincoln2001: 379 SD1 : 521 FD5 :3129 02_03 :274 Median :2.000
Lincoln2003: 286 SD2 : 186 03_04 :273 Mean :2.336
Lincoln2004: 178 SD3 : 158 15_16 :242 3rd Qu.:3.000
Lincoln1998: 168 SD4 : 155 16_17 :201 Max. :6.000
(Other) : 373 (Other): 0 (Other):777
Rotation StartDate MidDate FinishDate Interval
Min. :1.000 Min. :1996-11-01 Min. :1996-12-27 Min. :1997-02-21 Min. : 0.00
1st Qu.:1.000 1st Qu.:2000-11-14 1st Qu.:2000-12-29 1st Qu.:2001-01-24 1st Qu.: 20.00
Median :2.000 Median :2001-07-05 Median :2001-08-16 Median :2001-09-29 Median : 33.00
Mean :2.952 Mean :2004-06-08 Mean :2004-07-09 Mean :2004-08-10 Mean : 37.88
3rd Qu.:4.000 3rd Qu.:2004-02-08 3rd Qu.:2004-02-28 3rd Qu.:2004-03-19 3rd Qu.: 52.00
Max. :7.000 Max. :2017-12-04 Max. :2017-12-25 Max. :2018-01-15 Max. :122.00
VariableUnits Time Observed StdDEV ExperimentID TreatmentID
% : 0 12:00:00:3198 Min. : 0.00 Min. : 0.0000 E1: 916 ILL :1041
cm :453 1st Qu.: 5.35 1st Qu.: 0.0000 E2:1020 DLL : 461
fractio0l:575 Median : 20.03 Median : 0.3462 E3: 586 ILLF5 : 415
Fraction :216 Mean : 661.95 Mean : 94.5968 E4: 0 ILLS1 : 263
kg/ha :892 3rd Qu.: 649.67 3rd Qu.: 35.7600 E5: 676 DLLS1 : 258
m2/m2 :537 Max. :8556.38 Max. :2532.5264 IHHF5 : 192
mm :525 NA's :648 (Other): 568
ID GrowthSeason1 Rotation1 ExpUnitCode Clock.Today1
E3ILL :586 Gs_1:1044 Rt_1:967 Iversen_91DefoliationLLGs_2Rt_1: 59 Min. :1997-01-28 12:00:00
E1DLL :461 Gs_2:1127 Rt_2:646 Iversen_91DefoliationLLGs_1Rt_1: 48 1st Qu.:2001-01-06 12:00:00
E1ILL :455 Gs_3: 388 Rt_3:457 Iversen_8WaterdryGs_5Rt_1 : 42 Median :2001-09-15 12:00:00
E5ILLF5:415 Gs_4: 228 Rt_4:354 Iversen_8WaterirrGs_5Rt_1 : 42 Mean :2004-07-17 03:12:42
E2ILLS1:263 Gs_5: 369 Rt_5:354 Iversen_91DefoliationLLGs_1Rt_4: 42 3rd Qu.:2004-03-02 12:00:00
E2DLLS1:258 Gs_6: 42 Rt_6:317 Iversen_91DefoliationLLGs_1Rt_5: 42 Max. :2017-12-29 12:00:00
(Other):760 Rt_7:103 (Other) :2923
GrowthSeason2 Rotation2 Predicted
Y1(00_01): 594 R2 :646 Min. : 0.000
Y2(01_02): 426 S1 :634 1st Qu.: 5.548
Y5(00_01): 369 R3 :457 Median : 133.087
Y1(02_03): 274 R4 :354 Mean : 773.700
Y2(03_04): 273 R5 :354 3rd Qu.: 690.120
Y2(15_16): 242 R1 :333 Max. :7999.825
(Other) :1020 (Other):420
str(mergedf)
'data.frame': 3198 obs. of 30 variables:
$ Clock.Today : Date, format: "1997-01-28" "1997-01-28" "1997-02-17" "1997-02-17" ...
$ Name : Factor w/ 25 levels "Iversen_121DefoliationHHFDFD5",..: 15 16 15 16 15 16 15 16 15 16 ...
$ Variable : Factor w/ 19 levels "Branch","CrownWt",..: 13 13 6 6 13 13 13 13 13 13 ...
$ Collection : Factor w/ 5 levels "1997_2001","2000_2002",..: 1 1 1 1 1 1 1 1 1 1 ...
$ Experiment : Factor w/ 11 levels "Lincoln1997",..: 1 1 1 1 1 1 1 1 1 1 ...
$ Water : Factor w/ 2 levels "dry","irr": 1 2 1 2 1 2 1 2 1 2 ...
$ Defoliation : Factor w/ 2 levels "HH","LL": 2 2 2 2 2 2 2 2 2 2 ...
$ SowingDate : Factor w/ 12 levels "no","No","SD1",..: 2 2 2 2 2 2 2 2 2 2 ...
$ FD : Factor w/ 3 levels "FD10","FD2","FD5": 3 3 3 3 3 3 3 3 3 3 ...
$ Period : Factor w/ 16 levels "00_01","01_02",..: 13 13 13 13 13 13 13 13 14 14 ...
$ GrowthSeason : int 1 1 1 1 1 1 1 1 2 2 ...
$ Rotation : int 1 1 1 1 1 1 2 2 1 1 ...
$ StartDate : Date, format: "1996-11-01" "1996-11-01" "1996-11-01" "1996-11-01" ...
$ MidDate : Date, format: "1996-12-27" "1996-12-27" "1996-12-27" "1996-12-27" ...
$ FinishDate : Date, format: "1997-02-21" "1997-02-21" "1997-02-21" "1997-02-21" ...
$ Interval : int 88 88 108 108 112 112 103 103 51 51 ...
$ VariableUnits: Factor w/ 7 levels "%","cm","fractio0l",..: 5 5 6 6 5 5 5 5 5 5 ...
$ Time : Factor w/ 1 level "12:00:00": 1 1 1 1 1 1 1 1 1 1 ...
$ Observed : num 4613.3 4613.3 4.47 4.32 5400 ...
$ StdDEV : num 0 0 0 0 0 0 0 0 0 0 ...
$ ExperimentID : Factor w/ 5 levels "E1","E2","E3",..: 1 1 1 1 1 1 1 1 1 1 ...
$ TreatmentID : Factor w/ 20 levels "DLL","DLLS1",..: 1 13 1 13 1 13 1 13 1 13 ...
$ ID : Factor w/ 25 levels "E1DLL","E1ILL",..: 1 2 1 2 1 2 1 2 1 2 ...
$ GrowthSeason1: Factor w/ 6 levels "Gs_1","Gs_2",..: 1 1 1 1 1 1 1 1 2 2 ...
$ Rotation1 : Factor w/ 7 levels "Rt_1","Rt_2",..: 1 1 1 1 1 1 2 2 1 1 ...
$ ExpUnitCode : Factor w/ 199 levels "Iversen_8WaterdryGs_1Rt_1",..: 1 31 1 31 1 31 2 32 3 33 ...
$ Clock.Today1 : POSIXct, format: "1997-01-28 12:00:00" "1997-01-28 12:00:00" "1997-02-17 12:00:00" "1997-02-17 12:00:00" ...
$ GrowthSeason2: Factor w/ 18 levels "Y1(96_97)","Y2(97_98)",..: 1 1 1 1 1 1 1 1 2 2 ...
$ Rotation2 : Factor w/ 8 levels "R1","R2","R3",..: 1 1 1 1 1 1 2 2 1 1 ...
$ Predicted : num 69.05 69.05 4.82 4.82 2939.64 ...
mergedf %>%
dplyr::filter(Collection=="2000_2002")%>%
dplyr::filter(Variable== "NodeNumber") %>%
dplyr::filter(Water== "irr")%>%
dplyr::filter(Defoliation== "LL")%>%
ggplot(aes(x=Observed, y= Predicted,
colour= factor(Name))) +
geom_point(size=3)+theme_bw()+
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="darkgrey") +
geom_abline(intercept = 0, slope = 1) +
coord_fixed(ratio = 1)+
ggtitle("Node Number")+
facet_grid(GrowthSeason~Rotation)+
theme(legend.title=element_blank())+xlab("Observed")+ylab("Predicted")+
theme(axis.title.x=element_text(face="bold",colour="black",size = 12))+
theme(axis.title.y=element_text(face="bold",colour="black",size = 12))

mergedf %>%
dplyr::filter(Collection=="1997_2001")%>%
dplyr::filter(Variable== "NodeNumber") %>%
dplyr::filter(Water== "irr")%>%
dplyr::filter(Defoliation== "LL")%>%
ggplot(aes(x=Observed, y= Predicted,
colour= factor(Name))) +
geom_point(size=3)+theme_bw() +
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="darkgrey") +
geom_abline(intercept = 0, slope = 1) +
coord_fixed(ratio = 1) +
ggtitle("Node Number") +
facet_grid(GrowthSeason~Rotation)+
theme(legend.title=element_blank(),legend.position = "blank")+xlab("Observed")+ylab("Predicted")+
theme(axis.title.x=element_text(face="bold",colour="black",size = 12))+
theme(axis.title.y=element_text(face="bold",colour="black",size = 12))

mergedf %>%
dplyr::filter(Collection=="1997_2001")%>%
dplyr::filter(Variable== "NodeNumber") %>%
dplyr::filter(Water== "irr")%>%
dplyr::filter(Defoliation== "LL")%>%
ggplot(aes(x=Observed, y= Predicted,
colour= factor(Name))) +
geom_point(size=3)+theme_bw() +
geom_smooth(method = "lm", se = TRUE, linetype = 1, colour="darkgrey") +
geom_abline(intercept = 0, slope = 1) +
coord_fixed(ratio = 1) +
ggtitle("Node Number") +
# facet_grid(.~Rotation) + # Rotation
facet_wrap(~GrowthSeason, ncol = 4)+
theme(legend.title=element_blank(),legend.position = "blank")+xlab("Observed")+ylab("Predicted")+
theme(axis.title.x=element_text(face="bold",colour="black",size = 12))+
theme(axis.title.y=element_text(face="bold",colour="black",size = 12))

RMSE
str(mergedf)
'data.frame': 3198 obs. of 30 variables:
$ Clock.Today : Date, format: "1997-01-28" "1997-01-28" "1997-02-17" "1997-02-17" ...
$ Name : Factor w/ 25 levels "Iversen_121DefoliationHHFDFD5",..: 15 16 15 16 15 16 15 16 15 16 ...
$ Variable : Factor w/ 19 levels "Branch","CrownWt",..: 13 13 6 6 13 13 13 13 13 13 ...
$ Collection : Factor w/ 5 levels "1997_2001","2000_2002",..: 1 1 1 1 1 1 1 1 1 1 ...
$ Experiment : Factor w/ 11 levels "Lincoln1997",..: 1 1 1 1 1 1 1 1 1 1 ...
$ Water : Factor w/ 2 levels "dry","irr": 1 2 1 2 1 2 1 2 1 2 ...
$ Defoliation : Factor w/ 2 levels "HH","LL": 2 2 2 2 2 2 2 2 2 2 ...
$ SowingDate : Factor w/ 12 levels "no","No","SD1",..: 2 2 2 2 2 2 2 2 2 2 ...
$ FD : Factor w/ 3 levels "FD10","FD2","FD5": 3 3 3 3 3 3 3 3 3 3 ...
$ Period : Factor w/ 16 levels "00_01","01_02",..: 13 13 13 13 13 13 13 13 14 14 ...
$ GrowthSeason : int 1 1 1 1 1 1 1 1 2 2 ...
$ Rotation : int 1 1 1 1 1 1 2 2 1 1 ...
$ StartDate : Date, format: "1996-11-01" "1996-11-01" "1996-11-01" "1996-11-01" ...
$ MidDate : Date, format: "1996-12-27" "1996-12-27" "1996-12-27" "1996-12-27" ...
$ FinishDate : Date, format: "1997-02-21" "1997-02-21" "1997-02-21" "1997-02-21" ...
$ Interval : int 88 88 108 108 112 112 103 103 51 51 ...
$ VariableUnits: Factor w/ 7 levels "%","cm","fractio0l",..: 5 5 6 6 5 5 5 5 5 5 ...
$ Time : Factor w/ 1 level "12:00:00": 1 1 1 1 1 1 1 1 1 1 ...
$ Observed : num 4613.3 4613.3 4.47 4.32 5400 ...
$ StdDEV : num 0 0 0 0 0 0 0 0 0 0 ...
$ ExperimentID : Factor w/ 5 levels "E1","E2","E3",..: 1 1 1 1 1 1 1 1 1 1 ...
$ TreatmentID : Factor w/ 20 levels "DLL","DLLS1",..: 1 13 1 13 1 13 1 13 1 13 ...
$ ID : Factor w/ 25 levels "E1DLL","E1ILL",..: 1 2 1 2 1 2 1 2 1 2 ...
$ GrowthSeason1: Factor w/ 6 levels "Gs_1","Gs_2",..: 1 1 1 1 1 1 1 1 2 2 ...
$ Rotation1 : Factor w/ 7 levels "Rt_1","Rt_2",..: 1 1 1 1 1 1 2 2 1 1 ...
$ ExpUnitCode : Factor w/ 199 levels "Iversen_8WaterdryGs_1Rt_1",..: 1 31 1 31 1 31 2 32 3 33 ...
$ Clock.Today1 : POSIXct, format: "1997-01-28 12:00:00" "1997-01-28 12:00:00" "1997-02-17 12:00:00" "1997-02-17 12:00:00" ...
$ GrowthSeason2: Factor w/ 18 levels "Y1(96_97)","Y2(97_98)",..: 1 1 1 1 1 1 1 1 2 2 ...
$ Rotation2 : Factor w/ 8 levels "R1","R2","R3",..: 1 1 1 1 1 1 2 2 1 1 ...
$ Predicted : num 69.05 69.05 4.82 4.82 2939.64 ...
mergedf %>%
dplyr::filter(Variable== "NodeNumber") %>%
dplyr::filter(Water== "irr")%>%
dplyr::filter(Defoliation== "LL")%>%
#filter(Variable == "NodeNumber") %>%
filter(Collection!="2010_2012")%>%
mutate(Rotation= as.factor(Rotation))%>%
mutate(GrowthSeason=as.factor(GrowthSeason))%>%
group_by(ID) %>%
summarise(
n = n(),
r2 = gauchStats(Predicted,Observed)[5],
# rmse = round(rmse(Predicted,Observed),0),
r_rmse = round(rmse(Predicted,Observed)/mean(Observed)*100,1),
nse = round(NSE(Predicted,Observed),2),
sb = gauchStats(Predicted,Observed)[1],
nu = gauchStats(Predicted,Observed)[2],
lc = gauchStats(Predicted,Observed)[3]
)
NA
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KIyMjTm9kZU51bWJlciBhbmFseXNpcw0KDQpgYGB7ciBMb2FkLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04fQ0KDQpsaWJyYXJ5KHBseXIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShsdWJyaWRhdGUpICAgDQpsaWJyYXJ5KGh5ZHJvR09GKQ0KbGlicmFyeSh4dGFibGUpDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoUlNRTGl0ZSkNCmxpYnJhcnkoYWdyaWNvbGFlKQ0KbGlicmFyeShzY2FsZXMpDQpsaWJyYXJ5KHpvbykNCg0KZGV0YWNoKHBhY2thZ2U6cGx5cikNCmBgYA0KDQojICMjIyBsb2FkIG9icyBkYXRhDQpgYGB7cn0NCnVwRGlyIDwtICJEOi9SL0NvbWJpbmVkRGF0YS8iDQpvYnNEYXRhIDwtICJEOi9SL0NvbWJpbmVkRGF0YS8iDQoNCm9ic0FsbCA8LSByZWFkLnRhYmxlKHBhc3RlMChvYnNEYXRhLCAiT2JzQWxsLnR4dCIpLA0KICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFRSVUUpDQpvYnNBMTwtIG9ic0FsbCAlPiUNCiAgZHBseXI6OmZpbHRlcihDb2xsZWN0aW9uPT0iMjAwMF8yMDAyIiklPiUNCiAgbXV0YXRlKFN0YXJ0RGF0ZT1kbXkoU3RhcnREYXRlKSxNaWREYXRlPWRteShNaWREYXRlKSxGaW5pc2hEYXRlPWRteShGaW5pc2hEYXRlKSxDbG9jay5Ub2RheT1kbXkoQ2xvY2suVG9kYXkpKSAlPiUNCiAgI211dGF0ZShTb3dpbmdEYXRlPWFzLmZhY3RvcihpZmVsc2UoU293aW5nRGF0ZT09Im5vIiwiU2RfTm8iLHBhc3RlMCgiU2RfIixTb3dpbmdEYXRlKSkpKSAlPiUgIyBhc3N1bWUgdGhpcyBpcyB0eXBvIHRvIGJlIGZpeGVkPw0KICBtdXRhdGUoR3Jvd3RoU2Vhc29uMT1hcy5mYWN0b3IocGFzdGUwKCJHc18iLEdyb3d0aFNlYXNvbikpKSAlPiUgIyBjcmVhdGluZyBtb3JlIGludHVpdGl2ZSBsYWJlbHMgaGVyZQ0KICBtdXRhdGUoUm90YXRpb24xPWFzLmZhY3RvcihwYXN0ZTAoIlJ0XyIsUm90YXRpb24pKSkgJT4lDQogIG11dGF0ZShFeHBVbml0Q29kZT1hcy5mYWN0b3IocGFzdGUwKE5hbWUsR3Jvd3RoU2Vhc29uMSxSb3RhdGlvbjEpKSkgJT4lDQogIG11dGF0ZShDbG9jay5Ub2RheTEgPSBhcy5QT1NJWGN0KHBhc3RlKENsb2NrLlRvZGF5LFRpbWUpLGZvcm1hdD0iJVktJW0tJWQgJUg6JU06JVMiKSklPiUNCiAgbXV0YXRlKEdyb3d0aFNlYXNvbjI9YXMuZmFjdG9yKHBhc3RlMCgiWSIsR3Jvd3RoU2Vhc29uLCIoIixQZXJpb2QsIikiKSkpICU+JQ0KIG11dGF0ZShSb3RhdGlvbjI9YXMuZmFjdG9yKGlmZWxzZShSb3RhdGlvbj09IjEiLHBhc3RlMCgiUyIsUm90YXRpb24pLHBhc3RlMCgiUiIsUm90YXRpb24pKSkpDQoNCm9ic0E0PC0gb2JzQWxsICU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbGxlY3Rpb249PSIyMDE0XzIwMTgiKSU+JQ0KICBtdXRhdGUoU3RhcnREYXRlPWRteShTdGFydERhdGUpLE1pZERhdGU9ZG15KE1pZERhdGUpLEZpbmlzaERhdGU9ZG15KEZpbmlzaERhdGUpLENsb2NrLlRvZGF5PWRteShDbG9jay5Ub2RheSkpICU+JQ0KICAjbXV0YXRlKFNvd2luZ0RhdGU9YXMuZmFjdG9yKGlmZWxzZShTb3dpbmdEYXRlPT0ibm8iLCJTZF9ObyIscGFzdGUwKCJTZF8iLFNvd2luZ0RhdGUpKSkpICU+JSAjIGFzc3VtZSB0aGlzIGlzIHR5cG8gdG8gYmUgZml4ZWQ/DQogIG11dGF0ZShHcm93dGhTZWFzb24xPWFzLmZhY3RvcihwYXN0ZTAoIkdzXyIsR3Jvd3RoU2Vhc29uKSkpICU+JSAjIGNyZWF0aW5nIG1vcmUgaW50dWl0aXZlIGxhYmVscyBoZXJlDQogIG11dGF0ZShSb3RhdGlvbjE9YXMuZmFjdG9yKHBhc3RlMCgiUnRfIixSb3RhdGlvbikpKSAlPiUNCiAgbXV0YXRlKEV4cFVuaXRDb2RlPWFzLmZhY3RvcihwYXN0ZTAoTmFtZSxHcm93dGhTZWFzb24xLFJvdGF0aW9uMSkpKSAlPiUNCiAgbXV0YXRlKENsb2NrLlRvZGF5MSA9IGFzLlBPU0lYY3QocGFzdGUoQ2xvY2suVG9kYXksVGltZSksZm9ybWF0PSIlWS0lbS0lZCAlSDolTTolUyIpKSU+JQ0KICBtdXRhdGUoR3Jvd3RoU2Vhc29uMj1hcy5mYWN0b3IocGFzdGUwKCJZIixHcm93dGhTZWFzb24sIigiLFBlcmlvZCwiKSIpKSkgJT4lDQogIG11dGF0ZShSb3RhdGlvbjI9YXMuZmFjdG9yKGlmZWxzZShSb3RhdGlvbj09IjEiLHBhc3RlMCgiUyIsUm90YXRpb24pLHBhc3RlMCgiUiIsUm90YXRpb24pKSkpDQogDQoNCiAgb2JzQTI8LSBvYnNBbGwgJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29sbGVjdGlvbj09IjE5OTdfMjAwMSIpJT4lDQogIG11dGF0ZShTdGFydERhdGU9ZG15KFN0YXJ0RGF0ZSksTWlkRGF0ZT1kbXkoTWlkRGF0ZSksRmluaXNoRGF0ZT1kbXkoRmluaXNoRGF0ZSksQ2xvY2suVG9kYXk9ZG15KENsb2NrLlRvZGF5KSkgJT4lDQogICNtdXRhdGUoU293aW5nRGF0ZT1hcy5mYWN0b3IoaWZlbHNlKFNvd2luZ0RhdGU9PSJubyIsIlNkX05vIixwYXN0ZTAoIlNkXyIsU293aW5nRGF0ZSkpKSkgJT4lICMgYXNzdW1lIHRoaXMgaXMgdHlwbyB0byBiZSBmaXhlZD8NCiAgbXV0YXRlKEdyb3d0aFNlYXNvbjE9YXMuZmFjdG9yKHBhc3RlMCgiR3NfIixHcm93dGhTZWFzb24pKSkgJT4lICMgY3JlYXRpbmcgbW9yZSBpbnR1aXRpdmUgbGFiZWxzIGhlcmUNCiAgbXV0YXRlKFJvdGF0aW9uMT1hcy5mYWN0b3IocGFzdGUwKCJSdF8iLFJvdGF0aW9uKSkpICU+JQ0KICBtdXRhdGUoRXhwVW5pdENvZGU9YXMuZmFjdG9yKHBhc3RlMChOYW1lLEdyb3d0aFNlYXNvbjEsUm90YXRpb24xKSkpICU+JQ0KICBtdXRhdGUoQ2xvY2suVG9kYXkxID0gYXMuUE9TSVhjdChwYXN0ZShDbG9jay5Ub2RheSxUaW1lKSxmb3JtYXQ9IiVZLSVtLSVkICVIOiVNOiVTIikpJT4lDQogIG11dGF0ZShHcm93dGhTZWFzb24yPWFzLmZhY3RvcihwYXN0ZTAoIlkiLEdyb3d0aFNlYXNvbiwiKCIsUGVyaW9kLCIpIikpKSAlPiUNCiAgbXV0YXRlKFJvdGF0aW9uMj1hcy5mYWN0b3IocGFzdGUwKCJSIixSb3RhdGlvbikpKQ0KICANCg0KICBvYnNBMzwtIG9ic0FsbCAlPiUNCiAgZHBseXI6OmZpbHRlcihDb2xsZWN0aW9uPT0iMjAwMl8yMDA0IiklPiUNCiAgbXV0YXRlKFN0YXJ0RGF0ZT1kbXkoU3RhcnREYXRlKSxNaWREYXRlPWRteShNaWREYXRlKSxGaW5pc2hEYXRlPWRteShGaW5pc2hEYXRlKSxDbG9jay5Ub2RheT1kbXkoQ2xvY2suVG9kYXkpKSAlPiUNCiAgI211dGF0ZShTb3dpbmdEYXRlPWFzLmZhY3RvcihpZmVsc2UoU293aW5nRGF0ZT09Im5vIiwiU2RfTm8iLHBhc3RlMCgiU2RfIixTb3dpbmdEYXRlKSkpKSAlPiUgIyBhc3N1bWUgdGhpcyBpcyB0eXBvIHRvIGJlIGZpeGVkPw0KICBtdXRhdGUoR3Jvd3RoU2Vhc29uMT1hcy5mYWN0b3IocGFzdGUwKCJHc18iLEdyb3d0aFNlYXNvbikpKSAlPiUgIyBjcmVhdGluZyBtb3JlIGludHVpdGl2ZSBsYWJlbHMgaGVyZQ0KICBtdXRhdGUoUm90YXRpb24xPWFzLmZhY3RvcihwYXN0ZTAoIlJ0XyIsUm90YXRpb24pKSkgJT4lDQogIG11dGF0ZShFeHBVbml0Q29kZT1hcy5mYWN0b3IocGFzdGUwKE5hbWUsR3Jvd3RoU2Vhc29uMSxSb3RhdGlvbjEpKSkgJT4lDQogIG11dGF0ZShDbG9jay5Ub2RheTEgPSBhcy5QT1NJWGN0KHBhc3RlKENsb2NrLlRvZGF5LFRpbWUpLGZvcm1hdD0iJVktJW0tJWQgJUg6JU06JVMiKSklPiUNCiAgbXV0YXRlKEdyb3d0aFNlYXNvbjI9YXMuZmFjdG9yKHBhc3RlMCgiWSIsR3Jvd3RoU2Vhc29uLCIoIixQZXJpb2QsIikiKSkpICU+JQ0KICBtdXRhdGUoUm90YXRpb24yPWFzLmZhY3RvcihwYXN0ZTAoIlIiLFJvdGF0aW9uKSkpDQogIA0Kb2JzQTwtcmJpbmQob2JzQTIsb2JzQTMsb2JzQTEsb2JzQTQpDQpzdW1tYXJ5KG9ic0EpDQogb2JzQQ0KYGBgDQpgYGB7cn0NCnVwRGlyIDwtICJEOi9SLyINCm9ic0RhdGEgPC0gIkQ6L1IvVHRBbGwvIg0KDQpUdDwtIHJlYWQudGFibGUocGFzdGUwKG9ic0RhdGEsICJkZi5hbGwudHh0IiksDQogICAgICAgICAgICAgICBoZWFkZXIgPSBUUlVFKQ0KVHRBIDwtIFR0ICU+JSBtdXRhdGUoQ2xvY2suVG9kYXk9ZG15KENsb2NrLlRvZGF5KSwgRXhwVW5pdENvZGU9YXMuZmFjdG9yKEV4cE5hbWUpKQ0KVHRBDQpPYnNIIDwtbWVyZ2Uob2JzQSxUdEEsYnk9YygiQ2xvY2suVG9kYXkiLCJFeHBVbml0Q29kZSIpKSAlPiUNCiAgbXV0YXRlKEdyb3d0aFJvdGF0aW9uPWFzLmZhY3RvcihwYXN0ZTAoR3Jvd3RoU2Vhc29uLngsUm90YXRpb24ueCkpKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKFdhdGVyLng9PSJpcnIiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKERlZm9saWF0aW9uLng9PSJMTCIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoVmFyaWFibGU9PSJOb2RlTnVtYmVyIikNCiAgc3VtbWFyeShPYnNIKQ0KDQpgYGANCmBgYHtyfQ0KbXl0aGVtZTE8LXRoZW1lKA0KICAgICBwYW5lbC5zcGFjaW5nPXVuaXQoLjAxLCAibGluZXMiKSwNCiAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsc2l6ZT0xKSwgDQogICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siLHNpemUgPSAxKSwNCiAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0LGFuZ2xlPTkwLCB2anVzdD0wLjUsIGhqdXN0ID0gMSksDQogICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAxNCksDQogICAgIGF4aXMudGl0bGUueD1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDE0KSwNCiAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfdGV4dChmYWNlPSJib2xkIixjb2xvdXI9ImJsYWNrIixzaXplID0gMTQpLA0KICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAid2hpdGUiLHNpemU9MSksDQogICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBhbmdsZT0wLCBmYWNlID0gInBsYWluIiksIA0KICAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgZmFjZT0icGxhaW4iKSwNCiAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91cj0iYmxhY2siLCBzaXplPTE0LCBmYWNlPSJib2xkIiksDQogICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCB2anVzdCA9IDAuNSwgc2l6ZSA9IDE0KSkNCg0KbXl0aGVtZTM8LXRoZW1lKA0KICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIsIHNpemU9MTQsIGZhY2U9ImJvbGQiKSwNCiAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIsIHNpemUgPSAxNCxmYWNlPSJwbGFpbiIpLA0KICAgICBwYW5lbC5zcGFjaW5nPXVuaXQoLjAxLCAibGluZXMiKSwNCiAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsc2l6ZT0xKSwgDQogICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siLHNpemUgPSAxKSwNCiAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0LCB2anVzdD0wLjUsIGhqdXN0ID0gMSksDQogICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAxNCksDQogICAgIGF4aXMudGl0bGUueD1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDE0KSwNCiAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfdGV4dChmYWNlPSJib2xkIixjb2xvdXI9ImJsYWNrIixzaXplID0gMTQpLA0KICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAid2hpdGUiLHNpemU9MSksDQogICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBhbmdsZT0wLCBmYWNlID0gInBsYWluIiksIA0KICAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgZmFjZT0icGxhaW4iKSwNCiAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHZqdXN0ID0gMC41LCBzaXplID0gMTQpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIGxlZ2VuZC5ib3ggPSAidmVydGljYWwiKQ0KYGBgDQoNCiMjI0V4YW1wbGVzIGZvciBvcmRlciB0ZXh0IA0KYGBge3J9DQoNCngxIDwtIGMoIndoaXRlIiwid2hpdGUiLCJibHVlIiwiZ3JlZW4iLCJyZWQiLCJibHVlIiwicmVkIikNCiBvcmQgPC0gYygicmVkIiwid2hpdGUiLCJibHVlIiwiZ3JlZW4iKQ0KIGYxIDwtIGZhY3Rvcih4MSxsZXZlbHM9b3JkKQ0KIHNvcnQoZjEpDQp4MiA8LSBhcy5jaGFyYWN0ZXIoc29ydChmMSkpDQoNCnggPC0gYygid2hpdGUiLCJ3aGl0ZSIsImJsdWUiLCJncmVlbiIsInJlZCIsImJsdWUiLCJyZWQiKQ0KeSA8LSBjKCJyZWQiLCJ3aGl0ZSIsImJsdWUiLCJncmVlbiIpDQp4W29yZGVyKG1hdGNoKHgsIHkpKV0NCg0KDQpgYGANCg0KYGBge3IsZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OH0NCm9ic05vZGU8LU9ic0glPiUNCiAgZHBseXI6OmZpbHRlcihUYj09MSkNCg0KICBvYnNOb2RlMDwtb2JzTm9kZSU+JQ0KICBkcGx5cjo6ZmlsdGVyKE5hbWU9PSJJdmVyc2VuXzhXYXRlcmlyciIpDQogIG9ic05vZGUwJFJvdGF0aW9uMjwtIGZhY3RvcihvYnNOb2RlMCRSb3RhdGlvbjIsIGxldmVscz1jKCJSMSIsICJSMiIsICJSMyIsICJSNCIsICJSNSIsIlI2IiwgIlI3IikpDQogIG9ic05vZGUwJT4lICANCiAgZ2dwbG90KGFlcyh4PVR0X2Jyb2tlbl9zdW0sIHk9T2JzZXJ2ZWQpKStnZW9tX3BvaW50KHNpemU9MikrdGhlbWVfYncoKSt4bGFiKCJUaGVybWFsIHRpbWUgKLBDZCkgIikreWxhYigiTm9kZSBudW1iZXIiKStnZ3RpdGxlKHBhc3RlMCgiRTFJTEwiLCIoSXZlcnNlbl84V2F0ZXJpcnIpIikpICArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNTUwLCBieSA9MjAwKSwgbGltaXRzPWMoMCw0NTApKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxOCwgYnkgPTYpLCBsaW1pdHM9YygwLDE2KSkrDQogZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBsaW5ldHlwZSA9IDEsIGNvbG91cj0iYmx1ZSIpKw0KIGZhY2V0X2dyaWQoR3Jvd3RoU2Vhc29uMn5Sb3RhdGlvbjIpK215dGhlbWUxDQojdG8gc2F2ZSBhIGZpbmFsIGdyYXBoIA0KI2dnc2F2ZSgiRDovUi9QaWN0dXJlcy9Ob2RlL0l2ZXJzZW5fOFdhdGVyaXJybm9kZS5wbmciLCB3aWR0aD04LCBoZWlnaHQ9NiwgZHBpPTUwMCkNCg0KYGBgDQoNCmBgYHtyfQ0KI2ZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTgNCm9ic05vZGUxPC1vYnNOb2RlJT4lDQogICNkcGx5cjo6ZmlsdGVyKFR1cmUhPSJObyIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29sbGVjdGlvbj09IjIwMDBfMjAwMiIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoTmFtZT09Ikl2ZXJzZW5fOVNvd2luZ0RhdGVTRDFXYXRlcmlyciIpDQpvYnNOb2RlMSRSb3RhdGlvbjI8LSBmYWN0b3Iob2JzTm9kZTEkUm90YXRpb24yLCBsZXZlbHM9YygiUzEiLCAiUjIiLCAiUjMiLCAiUjQiLCAiUjUiLCJSNiIpKQ0Kb2JzTm9kZTElPiUNCiAgZ2dwbG90KGFlcyh4PVR0X2JldGFfc3VtLCB5PU9ic2VydmVkKSwgY29sb3VyPWZhY3RvcihOYW1lKSkrZ2VvbV9wb2ludChzaXplPTIpK3RoZW1lX2J3KCkreGxhYigiVGhlcm1hbCB0aW1lICiwQ2QpICIpK3NjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygwLDQyNSkpKw0KICB5bGFiKCJOb2RlIG51bWJlciIpK2dndGl0bGUocGFzdGUwKCJFMklMTFMxIiwiKEl2ZXJzZW5fOVNvd2luZ0RhdGVTRDFXYXRlcmlycikiKSkrDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNTUwLCBieSA9MjAwKSwgbGltaXRzPWMoMCw0NTApKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxOCwgYnkgPTYpLCBsaW1pdHM9YygwLDE2KSkrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSwgbGluZXR5cGUgPSAxLCBjb2xvdXI9ImJsdWUiKSsNCiBmYWNldF9ncmlkKEdyb3d0aFNlYXNvbjJ+Um90YXRpb24yKSsNCiB0aGVtZShheGlzLnRpdGxlLnk9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxNCkpK215dGhlbWUxDQogICNnZ3NhdmUoIkQ6L1IvUGljdHVyZXMvTm9kZS9JdmVyc2VuXzlTb3dpbmdEYXRlU0QxV2F0ZXJpcnJub2RlLnBuZyIsIHdpZHRoPTgsIGhlaWdodD00LCBkcGk9NTAwKQ0KICAgDQpgYGANCg0KYGBge3IsZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9MTB9DQpvYnNOb2RlMjwtb2JzTm9kZSU+JQ0KICAjZHBseXI6OmZpbHRlcihUdXJlIT0iTm8iKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbGxlY3Rpb249PSIyMDAwXzIwMDIiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKE5hbWU9PSJJdmVyc2VuXzlTb3dpbmdEYXRlU0QyV2F0ZXJpcnIiKQ0Kb2JzTm9kZTIkUm90YXRpb24yPC0gZmFjdG9yKG9ic05vZGUyJFJvdGF0aW9uMiwgbGV2ZWxzPWMoIlMxIiwgIlIyIiwgIlIzIiwgIlI0IiwgIlI1IiwiUjYiKSkNCm9ic05vZGUyJT4lDQogIGdncGxvdChhZXMoeD1UdF9iZXRhX3N1bSwgeT1PYnNlcnZlZCksIGNvbG91cj1mYWN0b3IoTmFtZSkpK2dlb21fcG9pbnQoc2l6ZT0yKSt0aGVtZV9idygpK3hsYWIoIlRoZXJtYWwgdGltZSAosENkKSIpK3lsYWIoIk5vZGUgbnVtYmVyIikrZ2d0aXRsZShwYXN0ZTAoIkUySUxMUzIiLCIoSXZlcnNlbl85U293aW5nRGF0ZVNEMldhdGVyaXJyKSIpKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBsaW5ldHlwZSA9IDEsIGNvbG91cj0iYmx1ZSIpKw0KIGZhY2V0X2dyaWQoR3Jvd3RoU2Vhc29uMn5Sb3RhdGlvbjIpKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDU1MCwgYnkgPTIwMCksIGxpbWl0cz1jKDAsNDUwKSkrDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMTgsIGJ5ID02KSwgbGltaXRzPWMoMCwxNikpKw0KI3JlbW92ZSBncmlkIGxpbmVzIA0KICB0aGVtZSgNCiAgICAgcGFuZWwuc3BhY2luZz11bml0KC4wMSwgImxpbmVzIiksDQogICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLHNpemU9MSksIA0KICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIixzaXplID0gMSksDQogICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAxNCwgdmp1c3Q9MC41LCBoanVzdCA9IDEpLA0KICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMTQpLA0KICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxNCksDQogICAgIGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDE0KSwNCiAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gIndoaXRlIixzaXplPTEpLA0KICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgYW5nbGU9MCwgZmFjZSA9ICJwbGFpbiIpLCANCiAgICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGZhY2U9InBsYWluIiksDQogICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIiwgc2l6ZT0xNCwgZmFjZT0iYm9sZCIpLA0KICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgdmp1c3QgPSAwLjUsIHNpemUgPSAxNCkpDQogICAjZ2dzYXZlKCJEOi9SL1BpY3R1cmVzL05vZGUvSXZlcnNlbl85U293aW5nRGF0ZVNEMldhdGVyaXJybm9kZS5wbmciLCB3aWR0aD04LCBoZWlnaHQ9MywgZHBpPTUwMCkNCiAgDQpgYGANCg0KYGBge3IsZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9MTB9DQpvYnNOb2RlMTwtb2JzTm9kZSU+JQ0KICAjZHBseXI6OmZpbHRlcihUdXJlIT0iTm8iKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbGxlY3Rpb249PSIyMDAwXzIwMDIiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKE5hbWU9PSJJdmVyc2VuXzlTb3dpbmdEYXRlU0QzV2F0ZXJpcnIiKQ0Kb2JzTm9kZTEkUm90YXRpb24yPC0gZmFjdG9yKG9ic05vZGUxJFJvdGF0aW9uMiwgbGV2ZWxzPWMoIlMxIiwgIlIyIiwgIlIzIiwgIlI0IiwgIlI1IiwiUjYiKSkNCm9ic05vZGUxJT4lDQogIGdncGxvdChhZXMoeD1UdF9iZXRhX3N1bSwgeT1PYnNlcnZlZCksIGNvbG91cj1mYWN0b3IoTmFtZSkpK2dlb21fcG9pbnQoc2l6ZT0yKSt0aGVtZV9idygpK3hsYWIoIlRoZXJtYWwgdGltZSAosENkKSIpK3lsYWIoIk5vZGUgbnVtYmVyIikrZ2d0aXRsZSgiRTJJTExTMyhJdmVyc2VuXzlTb3dpbmdEYXRlU0QzV2F0ZXJpcnIpIikrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSwgbGluZXR5cGUgPSAxLCBjb2xvdXI9ImJsdWUiKSsNCiBmYWNldF9ncmlkKEdyb3d0aFNlYXNvbjJ+Um90YXRpb24yKSt0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxMikpKw0KIHRoZW1lKGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDE0KSkrDQogICNyZW1vdmUgZ3JpZCBsaW5lcyANCiAgIHRoZW1lKA0KICAgICBwYW5lbC5zcGFjaW5nPXVuaXQoLjAxLCAibGluZXMiKSwNCiAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsc2l6ZT0xKSwgDQogICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siLHNpemUgPSAxKSwNCiAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0LCB2anVzdD0wLjUsIGhqdXN0ID0gMSksDQogICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAxNCksDQogICAgIGF4aXMudGl0bGUueD1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDE0KSwNCiAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfdGV4dChmYWNlPSJib2xkIixjb2xvdXI9ImJsYWNrIixzaXplID0gMTQpLA0KICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAid2hpdGUiLHNpemU9MSksDQogICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBhbmdsZT0wLCBmYWNlID0gInBsYWluIiksIA0KICAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgZmFjZT0icGxhaW4iKSwNCiAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91cj0iYmxhY2siLCBzaXplPTE0LCBmYWNlPSJib2xkIiksDQogICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCB2anVzdCA9IDAuNSwgc2l6ZSA9IDE0KSkNCiAgICNnZ3NhdmUoIkQ6L1IvUGljdHVyZXMvTm9kZS9JdmVyc2VuXzlTb3dpbmdEYXRlU0QzV2F0ZXJpcnJub2RlLnBuZyIsIHdpZHRoPTgsIGhlaWdodD0zLCBkcGk9NTAwKQ0KICANCmBgYA0KYGBge3IsZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9MTB9DQpvYnNOb2RlMTwtb2JzTm9kZSU+JQ0KICAjZHBseXI6OmZpbHRlcihUdXJlIT0iTm8iKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbGxlY3Rpb249PSIyMDAwXzIwMDIiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKE5hbWU9PSJJdmVyc2VuXzlTb3dpbmdEYXRlU0Q0V2F0ZXJpcnIiKQ0Kb2JzTm9kZTEkUm90YXRpb24yPC0gZmFjdG9yKG9ic05vZGUxJFJvdGF0aW9uMiwgbGV2ZWxzPWMoIlMxIiwgIlIyIiwgIlIzIiwgIlI0IiwgIlI1IiwiUjYiKSkNCm9ic05vZGUxJT4lDQogIGdncGxvdChhZXMoeD1UdF9iZXRhX3N1bSwgeT1PYnNlcnZlZCksIGNvbG91cj1mYWN0b3IoTmFtZSkpK2dlb21fcG9pbnQoc2l6ZT0yKSt0aGVtZV9idygpK3hsYWIoIlRoZXJtYWwgdGltZSAosENkKSIpK3lsYWIoIk5vZGUgbnVtYmVyIikrZ2d0aXRsZSgiRTJJTExTNChJdmVyc2VuXzlTb3dpbmdEYXRlU0Q0V2F0ZXJpcnIpIikrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSwgbGluZXR5cGUgPSAxLCBjb2xvdXI9ImJsdWUiKSsNCiBmYWNldF9ncmlkKEdyb3d0aFNlYXNvbjJ+Um90YXRpb24yKSt0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxMikpKw0KICAjcmVtb3ZlIGdyaWQgbGluZXMgDQogIHRoZW1lKA0KICAgICBwYW5lbC5zcGFjaW5nPXVuaXQoLjAxLCAibGluZXMiKSwNCiAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsc2l6ZT0xKSwgDQogICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siLHNpemUgPSAxKSwNCiAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0LCB2anVzdD0wLjUsIGhqdXN0ID0gMSksDQogICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAxNCksDQogICAgIGF4aXMudGl0bGUueD1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDE0KSwNCiAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfdGV4dChmYWNlPSJib2xkIixjb2xvdXI9ImJsYWNrIixzaXplID0gMTQpLA0KICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAid2hpdGUiLHNpemU9MSksDQogICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBhbmdsZT0wLCBmYWNlID0gInBsYWluIiksIA0KICAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgZmFjZT0icGxhaW4iKSwNCiAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91cj0iYmxhY2siLCBzaXplPTE0LCBmYWNlPSJib2xkIiksDQogICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCB2anVzdCA9IDAuNSwgc2l6ZSA9IDE0KSkNCiAgICNnZ3NhdmUoIkQ6L1IvUGljdHVyZXMvTm9kZS9JdmVyc2VuXzlTb3dpbmdEYXRlU0Q0V2F0ZXJpcnJub2RlLnBuZyIsIHdpZHRoPTgsIGhlaWdodD0zLCBkcGk9NTAwKQ0KICANCmBgYA0KDQoNCmBgYHtyLGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTh9DQpvYnNOb2RlNDwtb2JzTm9kZSU+JQ0KICAjZHBseXI6OmZpbHRlcihUdXJlIT0iTm8iKSU+JSAgDQogIGRwbHlyOjpmaWx0ZXIoTmFtZT09Ikl2ZXJzZW5fOTFEZWZvbGlhdGlvbkxMIikNCm9ic05vZGU0JFJvdGF0aW9uMjwtIGZhY3RvcihvYnNOb2RlNCRSb3RhdGlvbjIsIGxldmVscz1jKCJSMSIsICJSMiIsICJSMyIsICJSNCIsICJSNSIsIlI2IiwiUjciKSkgDQoNCm9ic05vZGU0JT4lDQpnZ3Bsb3QoYWVzKHg9VHRfYmV0YV9zdW0sIHk9T2JzZXJ2ZWQpLCBjb2xvdXI9ZmFjdG9yKE5hbWUpKStnZW9tX3BvaW50KHNpemU9MikrdGhlbWVfYncoKSt4bGFiKCJUaGVybWFsIHRpbWUgKLBDZCkiKSt5bGFiKCJOb2RlIG51bWJlciIpKw0KICBnZ3RpdGxlKCJFM0lMTChJdmVyc2VuXzkxRGVmb2xpYXRpb25MTCkiKSsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCA1NTAsIGJ5ID0yMDApLCBsaW1pdHM9YygwLDQ1MCkpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDE4LCBieSA9NiksIGxpbWl0cz1jKDAsMTYpKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBsaW5ldHlwZSA9IDEsIGNvbG91cj0iYmx1ZSIpKw0KIGZhY2V0X2dyaWQoR3Jvd3RoU2Vhc29uMn5Sb3RhdGlvbjIpKw0KICBteXRoZW1lMQ0KICAjZ2dzYXZlKCJEOi9SL1BpY3R1cmVzL05vZGUvSXZlcnNlbl85MURlZm9saWF0aW9uTExub2RlLnBuZyIsIHdpZHRoPTgsIGhlaWdodD01LCBkcGk9NTAwKQ0KICMgZ2dzYXZlKCJEOi9SL1BpY3R1cmVzL1Bvc3Rlci9ub2RlbnVtYmVyRTMucG5nIiwgd2lkdGg9OCwgaGVpZ2h0PTQsIGRwaT01MDApDQpgYGANCg0KYGBge3IsZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OH0NCm9ic05vZGVMTDwtb2JzTm9kZSU+JQ0KICBkcGx5cjo6ZmlsdGVyKE5hbWU9PSJJdmVyc2VuXzEyMURlZm9saWF0aW9uTExGREZENSIpDQpvYnNOb2RlTEwkUm90YXRpb24yPC0gZmFjdG9yKG9ic05vZGVMTCRSb3RhdGlvbjIsIGxldmVscz1jKCJTMSIsICJSMiIsICJSMyIsICJSNCIsICJSNSIsIlI2IiwiUjciKSkgDQoNCm9ic05vZGVMTCU+JQ0KICBnZ3Bsb3QoYWVzKHg9VHRfYmV0YV9zdW0sIHk9T2JzZXJ2ZWQpLCBjb2xvdXI9ZmFjdG9yKE5hbWUpKStnZW9tX3BvaW50KHNpemU9MikrdGhlbWVfYncoKSt4bGFiKCJUaGVybWFsIHRpbWUgKLBDZCkiKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCw0MzApKSsNCiAgeWxhYigiTm9kZSBudW1iZXIiKStnZ3RpdGxlKCJFNUlMTEY1KEl2ZXJzb25fMTIxRGVmb2xpYXRpb25MTEZERkQ1KSIpKw0KIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSwgbGluZXR5cGUgPSAxLCBjb2xvdXI9ImJsdWUiKSsNCiAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNTUwLCBieSA9MjAwKSwgbGltaXRzPWMoMCw0NTApKSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxOCwgYnkgPTYpLCBsaW1pdHM9YygwLDE2KSkrDQogZmFjZXRfZ3JpZChHcm93dGhTZWFzb24yflJvdGF0aW9uMikrDQogICBteXRoZW1lMQ0KICAjIGdnc2F2ZSgiRDovUi9QaWN0dXJlcy9Ob2RlL0l2ZXJzZW5fMTIxRGVmb2xpYXRpb25MTEZERkQ1bm9kZS5wbmciLCB3aWR0aD04LCBoZWlnaHQ9NiwgZHBpPTUwMCkNCg0KYGBgDQoNCiMjI1Igc3F1YXJlZCBhbmQgcGh5bGxvIGNhbGN1bGF0aW9uIGZvciBlYWNoIHJvdGF0aW9uDQojI1RUV0VTMQ0KIyNUYiBldmFsdWF0aW9uIA0KYGBge3J9DQojb2JzZWYxJT4lDQogIyBkcGx5cjo6ZmlsdGVyKFR1cmUhPSJObyIpDQogIyBzdGF0V0UxPC1PYnNIJT4lDQogIyBmaWx0ZXIoVmFyaWFibGUgPT0gIk5vZGVOdW1iZXIiKSAlPiUNCiAjICBmaWx0ZXIoV2F0ZXI9PSJpcnIiKSU+JQ0KICMgIGZpbHRlcihEZWZvbGlhdGlvbj09IkxMIiklPiUNCiAjICBtdXRhdGUoR3Jvd3RoU2Vhc29uPWZhY3RvcihHcm93dGhTZWFzb24pKSU+JQ0KICMgIGdyb3VwX2J5KEdyb3d0aFNlYXNvbixDb2xsZWN0aW9uKSAlPiUNCg0KdW5pVGIgPC0gdW5pcXVlKE9ic0gkVGIpDQoNClBoeUJldGEuYWxsIDwtIGRhdGEuZnJhbWUoKQ0KIA0KZm9yKGkgaW4gMTpsZW5ndGgodW5pVGIpKXsNCiAgDQogIE9ic0gxIDwtIE9ic0ggJT4lDQogIGZpbHRlcihUYj09dW5pVGJbaV0pDQogIA0KICAgT2JzSC5zdWIgPC0gT2JzSDEgJT4lDQogIGdyb3VwX2J5KE5hbWUsR3Jvd3RoU2Vhc29uLngsUm90YXRpb24ueCxDb2xsZWN0aW9uLFRtZWFuLFBwbSxUYixJRCxFeHBlcmltZW50SUQpICU+JQ0KICAgIGRvKG1vZC5iZXRhID0gbG0oVHRfYmV0YV9zdW1+T2JzZXJ2ZWQsZGF0YT0uKSklPiUNCiAgbXV0YXRlKFIyV0UgPSBzdW1tYXJ5KG1vZC5iZXRhKSRyLnNxdWFyZWQpJT4lDQogIG11dGF0ZShQaHlsbG9XRSA9IHN1bW1hcnkobW9kLmJldGEpJGNvZWZmWzJdKSU+JQ0KICBkcGx5cjo6c2VsZWN0KC1tb2QuYmV0YSkNCg0KICBQaHlCZXRhLmFsbCA8LSByYmluZChQaHlCZXRhLmFsbCwgT2JzSC5zdWIpDQp9DQogIA0KUGh5QmV0YS5hbGwNCndyaXRlLmNzdihQaHlCZXRhLmFsbCwiRDovUi9QaHlsbG9jaHJvbkRhdGEvUGh5QmV0YS5hbGwuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQoNCmBgYA0KYGBge3J9DQp1bmlUYiA8LSB1bmlxdWUoT2JzSCRUYikNCg0KUGh5YnJva2VuLmFsbCA8LSBkYXRhLmZyYW1lKCkNCiANCmZvcihpIGluIDE6bGVuZ3RoKHVuaVRiKSl7DQogIA0KICBPYnNIMSA8LSBPYnNIICU+JQ0KICBmaWx0ZXIoVGI9PXVuaVRiW2ldKQ0KICANCiAgIE9ic0guc3ViIDwtIE9ic0gxICU+JQ0KICBncm91cF9ieShOYW1lLEdyb3d0aFNlYXNvbi54LFJvdGF0aW9uLngsQ29sbGVjdGlvbixUbWVhbixQcG0sVGIsSUQsRXhwZXJpbWVudElEKSAlPiUNCiAgICBkbyhtb2QuYnJva2VuID0gbG0oVHRfYnJva2VuX3N1bX5PYnNlcnZlZCxkYXRhPS4pKSU+JQ0KICAgICNkbyhtb2QuZmljayA9IGxtKFR0X2ZpY2tfc3Vtfk9ic2VydmVkLGRhdGE9LikpJT4lDQogIG11dGF0ZShSMkJyID0gc3VtbWFyeShtb2QuYnJva2VuKSRyLnNxdWFyZWQpJT4lDQogIG11dGF0ZShQaHlsbG9CciA9IHN1bW1hcnkobW9kLmJyb2tlbikkY29lZmZbMl0pJT4lDQogIG11dGF0ZShQPWFub3ZhKG1vZC5icm9rZW4pJCdQcig+RiknWzFdKSU+JSANCiAgbXV0YXRlKGludGNwPSBzdW1tYXJ5KG1vZC5icm9rZW4pJGNvZWZmWzFdKSU+JSAgDQogIGRwbHlyOjpzZWxlY3QoLW1vZC5icm9rZW4pDQoNCiAgUGh5YnJva2VuLmFsbCA8LSByYmluZChQaHlicm9rZW4uYWxsLCBPYnNILnN1YikNCn0NCiAgDQpQaHlicm9rZW4uYWxsDQp3cml0ZS5jc3YoUGh5YnJva2VuLmFsbCwiRDovUi9QaHlsbG9jaHJvbkRhdGEvUGh5YnJva2VuLmFsbC5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkNCmBgYA0KDQpgYGB7cn0NCnVuaVRiIDwtIHVuaXF1ZShPYnNIJFRiKQ0KDQpQaHlmaWNrLmFsbCA8LSBkYXRhLmZyYW1lKCkNCiANCmZvcihpIGluIDE6bGVuZ3RoKHVuaVRiKSl7DQogIA0KICBPYnNIMSA8LSBPYnNIICU+JQ0KICBmaWx0ZXIoVGI9PXVuaVRiW2ldKQ0KICANCiAgIE9ic0guc3ViIDwtIE9ic0gxICU+JQ0KICBncm91cF9ieShOYW1lLEdyb3d0aFNlYXNvbi54LFJvdGF0aW9uLngsQ29sbGVjdGlvbixUbWVhbixQcG0sVGIsSUQsRXhwZXJpbWVudElEKSAlPiUNCiAgICBkbyhtb2QuZmljayA9IGxtKFR0X2ZpY2tfc3Vtfk9ic2VydmVkLGRhdGE9LikpJT4lDQogIG11dGF0ZShSMmZpID0gc3VtbWFyeShtb2QuZmljaykkci5zcXVhcmVkKSU+JQ0KICBtdXRhdGUoUGh5bGxvZmljayA9IHN1bW1hcnkobW9kLmZpY2spJGNvZWZmWzJdKSU+JQ0KICBkcGx5cjo6c2VsZWN0KC1tb2QuZmljaykNCg0KICBQaHlmaWNrLmFsbCA8LSByYmluZChQaHlmaWNrLmFsbCwgT2JzSC5zdWIpDQp9DQogIA0KUGh5Zmljay5hbGwNCndyaXRlLmNzdihQaHlmaWNrLmFsbCwiRDovUi9QaHlsbG9jaHJvbkRhdGEvUGh5Zmljay5hbGwuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KDQo8IS0tICMjVFRXRVMyIC0tPg0KPCEtLSBgYGB7cn0gLS0+DQo8IS0tICNvYnNlZjElPiUgLS0+DQo8IS0tICAjIGRwbHlyOjpmaWx0ZXIoVHVyZSE9Ik5vIikgLS0+DQo8IS0tIHN0YXRXRTI8LW9ic05vZGUlPiUgLS0+DQo8IS0tICBmaWx0ZXIoVmFyaWFibGUgPT0gIk5vZGVOdW1iZXIiKSAlPiUgLS0+DQo8IS0tICAgZmlsdGVyKFdhdGVyPT0iaXJyIiklPiUgLS0+DQo8IS0tICAgZmlsdGVyKERlZm9saWF0aW9uPT0iTEwiKSU+JSAtLT4NCjwhLS0gICBtdXRhdGUoR3Jvd3RoU2Vhc29uPWZhY3RvcihHcm93dGhTZWFzb24pKSU+JSAtLT4NCjwhLS0gICBncm91cF9ieShHcm93dGhTZWFzb24sQ29sbGVjdGlvbikgJT4lIC0tPg0KPCEtLSAgIGdyb3VwX2J5KE5hbWUsR3Jvd3RoU2Vhc29uLFJvdGF0aW9uLENvbGxlY3Rpb24sVG1lYW4sUG1lYW4pICU+JSAtLT4NCjwhLS0gICBkbyhtb2QgPSBsbShUVFdFUzJ+T2JzZXJ2ZWQsZGF0YT0uKSkgJT4lIC0tPg0KPCEtLSAgIG11dGF0ZShSMldFMiA9IHN1bW1hcnkobW9kKSRyLnNxdWFyZWQpICU+JSAtLT4NCjwhLS0gICBtdXRhdGUoUGh5bGxvV0UyID0gc3VtbWFyeShtb2QpJGNvZWZmWzJdKSAlPiUgLS0+DQo8IS0tICAgZHBseXI6OnNlbGVjdCgtbW9kKSAtLT4NCg0KPCEtLSAgIFdFMlIyPC1zdGF0V0UyJT4lIC0tPg0KPCEtLSAgIGdyb3VwX2J5KENvbGxlY3Rpb24pJT4lIC0tPg0KPCEtLSAgIG11dGF0ZShtZWFuUjJXRTI9bWVhbihSMldFMikpIC0tPg0KPCEtLSAgIFdFMlIyIC0tPg0KPCEtLSAgIHdyaXRlLmNzdihXRTJSMiwiRDovUi9QaHlsbG8vV0UyUjIuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpIC0tPg0KDQo8IS0tIGBgYCAtLT4NCg0KDQojIyMgQ29tYmluZSB0aGUgUGh5bGxvIGRhdGEgdG9nZXRoZXINCmBgYHtyLGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTEwLHdhcm5pbmc9RkFMU0V9DQptdWx0bWVyZ2UgPSBmdW5jdGlvbihteXBhdGgpew0KZmlsZW5hbWVzPWxpc3QuZmlsZXMocGF0aD1teXBhdGgsIGZ1bGwubmFtZXM9VFJVRSkNCmRhdGFsaXN0ID0gbGFwcGx5KGZpbGVuYW1lcywgZnVuY3Rpb24oeCl7cmVhZC5jc3YoZmlsZT14LGhlYWRlcj1UKX0pDQpSZWR1Y2UoZnVuY3Rpb24oeCx5KSB7bWVyZ2UoeCx5KX0sIGRhdGFsaXN0KX0NCg0KbWVyZ2VwaHk9bXVsdG1lcmdlKCJEOi9SL1BoeWxsb2Nocm9uRGF0YSIpDQptZXJnZXBoeQ0KDQpgYGANCg0KYGBge3J9DQoNCm1lcmdlUDwtbWVyZ2VwaHklPiUNCiAgIGRwbHlyOjpzZWxlY3QoTmFtZSxHcm93dGhTZWFzb24ueCxSb3RhdGlvbi54LENvbGxlY3Rpb24sVG1lYW4sIFBwbSxUYiwgUGh5bGxvV0UsUGh5bGxvQnIsUGh5bGxvZmljayxJRCxFeHBlcmltZW50SUQpICU+JQ0KICB0aWR5cjo6Z2F0aGVyKCJWYXJpYWJsZSIsIlBoeWxsbyIsUGh5bGxvV0U6UGh5bGxvZmljayklPiUNCiAgbXV0YXRlKFBoeWxsb1RiPWFzLmZhY3RvcihwYXN0ZTAoVmFyaWFibGUsVGIpKSklPiUNCiAgbXV0YXRlKEdyb3d0aFJvdGF0aW9uPWFzLmZhY3RvcihwYXN0ZTAoR3Jvd3RoU2Vhc29uLngsUm90YXRpb24ueCkpKQ0KdW5pcXVlKG1lcmdlUCkNCg0KbWVyZ2VQJE5hbWVzW21lcmdlUCROYW1lPT0iSXZlcnNlbl84V2F0ZXJpcnIiIF0gPC0iSThpcnIiDQptZXJnZVAkTmFtZXNbbWVyZ2VQJE5hbWU9PSJJdmVyc2VuXzkxRGVmb2xpYXRpb25MTCJdIDwtIkk5TEwiDQptZXJnZVAkTmFtZXNbbWVyZ2VQJE5hbWU9PSJJdmVyc2VuXzlTb3dpbmdEYXRlU0QxV2F0ZXJpcnIiXTwtIkk5U0QxaXJyIg0KbWVyZ2VQJE5hbWVzW21lcmdlUCROYW1lPT0iSXZlcnNlbl85U293aW5nRGF0ZVNEMldhdGVyaXJyIl08LSJJOVNEMmlyciINCm1lcmdlUCROYW1lc1ttZXJnZVAkTmFtZT09Ikl2ZXJzZW5fOVNvd2luZ0RhdGVTRDNXYXRlcmlyciJdPC0iSTlTRDNpcnIiDQptZXJnZVAkTmFtZXNbbWVyZ2VQJE5hbWU9PSJJdmVyc2VuXzlTb3dpbmdEYXRlU0Q0V2F0ZXJpcnIiXTwtIkk5U0Q0aXJyIg0KbWVyZ2VQJE5hbWVzW21lcmdlUCROYW1lPT0iSXZlcnNlbl8xMjFEZWZvbGlhdGlvbkxMRkRGRDUiXTwtIkkxMkRGNSINCm1lcmdlUA0KDQpgYGANCiMjUmVncmVzc2lvbiBjb2VmZmljaWVudA0KYGBge3J9DQptZXJnZVAlPiUNCiBnZ3Bsb3QoYWVzKHg9VG1lYW4sIHk9UGh5bGxvLCBjb2xvdXI9ZmFjdG9yKE5hbWVzKSkpK2dlb21fcG9pbnQoc2l6ZT0yKSt0aGVtZV9idygpKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFRSVUUsIGxpbmV0eXBlID0gMSwgY29sb3VyPSJkYXJrZ3JleSIpK3hsYWIoIk1lYW4gYWlyIHRlbXBlcmF0dXJlICiwQykiKSt5bGFiKCJQaHlsbG9jaHJvbiAosENkL0xlYWYpIikrDQogIGZhY2V0X3dyYXAoflBoeWxsb1RiLG5jb2wgPSAyKSsNCiAgdGhlbWUoYXhpcy50aXRsZS54PWVsZW1lbnRfdGV4dChmYWNlPSJib2xkIixjb2xvdXI9ImJsYWNrIixzaXplID0gMTIpKSsNCiB0aGVtZShheGlzLnRpdGxlLnk9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxMikpDQogIA0KYGBgDQoNCmBgYHtyfQ0KDQp1bmlQaHkgPC0gdW5pcXVlKG1lcmdlUCRQaHlsbG9UYikNClNsb3BlLmRmPC1kYXRhLmZyYW1lKCkNCg0KZm9yKGkgaW4gMTpsZW5ndGgodW5pUGh5KSApew0KICAgbWVyZ2VQLnN1YiA8LSBtZXJnZVAgJT4lDQogICAgIGZpbHRlcihQaHlsbG9UYj09dW5pUGh5W2ldKSU+JQ0KICAgZ3JvdXBfYnkoUGh5bGxvVGIpICU+JQ0KICAgIGRvKG1vZFBoeSA9IGxtKFRtZWFuflBoeWxsbyxkYXRhPS4pKSU+JQ0KICBtdXRhdGUoUjIgPSBzdW1tYXJ5KG1vZFBoeSkkci5zcXVhcmVkKSU+JQ0KICBtdXRhdGUoc2xvcGUgPSBzdW1tYXJ5KG1vZFBoeSkkY29lZmZbMl0pJT4lDQogIG11dGF0ZShQPWFub3ZhKG1vZFBoeSkkJ1ByKD5GKSdbMV0pJT4lICANCiAgZHBseXI6OnNlbGVjdCgtbW9kUGh5KQ0KICAgICANCiAgIFNsb3BlLmRmIDwtIHJiaW5kKFNsb3BlLmRmLG1lcmdlUC5zdWIpDQogIA0KfQ0KIFNsb3BlLmRmDQoNCmBgYA0KDQoNCiMjQ1YgY29lZmZlY2llbnQgb2YgdmFyaWF0aW9uDQpgYGB7cixmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD0xMH0NCm1lcmdlUA0KDQptZXJnZVBjdjwtbWVyZ2VQJT4lZ3JvdXBfYnkoQ29sbGVjdGlvbiwgVmFyaWFibGUpJT4lDQogbXV0YXRlKG1lYW5QaHlsbG89bWVhbihQaHlsbG8pKSU+JQ0KICBtdXRhdGUoU0RQaHlsbG89c2QoUGh5bGxvKSklPiUNCiAgbXV0YXRlKENWUGh5bGxvPVNEUGh5bGxvL21lYW5QaHlsbG8pDQptZXJnZVBjdg0KbWVyZ2VQY3YxPC1tZXJnZVBjdiU+JWdyb3VwX2J5KFZhcmlhYmxlKSU+JQ0KICBtdXRhdGUoQ1ZtZWFuPW1lYW4oQ1ZQaHlsbG8pKQ0KDQptZXJnZVBjdiU+JQ0KICBnZ3Bsb3QoYWVzKHg9UGh5bGxvVGIseT1DVlBoeWxsbyxjb2xvcj1mYWN0b3IoQ29sbGVjdGlvbikpKStnZW9tX3BvaW50KHNpemU9MikrdGhlbWVfYncoKQ0KICANCm1lcmdlUGN2MSU+JQ0KICBnZ3Bsb3QoYWVzKHg9UGh5bGxvVGIseT1DVm1lYW4pKStnZW9tX3BvaW50KHNpemU9MikrdGhlbWVfYncoKQ0KbWVyZ2VQY3YxDQoNCmBgYA0KDQojIyN4LWludGVyY2VwdCBtZXRob2QNCg0KYGBge3J9DQoNCkxBUjI8LU9ic0glPiUgIA0KICBncm91cF9ieShOYW1lLEdyb3d0aFNlYXNvbi54LFJvdGF0aW9uLngsQ29sbGVjdGlvbixUbWVhbixQcG0sR3Jvd3RoUm90YXRpb24sRXhwZXJpbWVudElELElEKSAlPiUNCiAgZG8obW9kID0gbG0oT2JzZXJ2ZWR+SW50ZXJ2YWwsZGF0YT0uKSkgJT4lDQogIG11dGF0ZShzbG9wZSA9IHN1bW1hcnkobW9kKSRjb2VmZlsyXSkgJT4lDQogICBtdXRhdGUoUjIgPSBzdW1tYXJ5KG1vZCkkci5zcXVhcmVkKSU+JQ0KICBtdXRhdGUoUD1hbm92YShtb2QpJCdQcig+RiknWzFdKSU+JSAgDQogIG11dGF0ZShpbnRjcD0gc3VtbWFyeShtb2QpJGNvZWZmWzFdKSU+JQ0KICBkcGx5cjo6c2VsZWN0KC1tb2QpDQpMQVIuYW5hPC0gT2JzSCU+JSAgDQogIGdyb3VwX2J5KENvbGxlY3Rpb24sRXhwZXJpbWVudElEKSAlPiUNCiAgZG8obW9kID0gbG0oT2JzZXJ2ZWR+SW50ZXJ2YWwsZGF0YT0uKSkgJT4lDQogIG11dGF0ZShzbG9wZSA9IHN1bW1hcnkobW9kKSRjb2VmZlsyXSkgJT4lDQogICBtdXRhdGUoUjIgPSBzdW1tYXJ5KG1vZCkkci5zcXVhcmVkKSU+JQ0KICBtdXRhdGUoUD1hbm92YShtb2QpJCdQcig+RiknWzFdKSU+JSAgDQogIG11dGF0ZShpbnRjcD0gc3VtbWFyeShtb2QpJGNvZWZmWzFdKSU+JQ0KICBkcGx5cjo6c2VsZWN0KC1tb2QpDQpgYGANCg0KYGBge3Isd2lkdGg9OCwgaGVpZ2h0PTZ9DQpsaWJyYXJ5KHBseXIpDQpMQVIuTkVXPC1MQVIyJT4lDQogIGRwbHlyOjpmaWx0ZXIoUm90YXRpb24ueCE9IjYifENvbGxlY3Rpb24hPSIxOTk3XzIwMDEiKSU+JQ0KICBtdXRhdGUoTkFSPXNsb3BlKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbGxlY3Rpb24hPSIyMDE0XzIwMTkiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbGxlY3Rpb24hPSIyMDEwXzIwMTIiKSU+JQ0KICBkcGx5cjo6c2VsZWN0KE5hbWUsIENvbGxlY3Rpb24sIEdyb3d0aFJvdGF0aW9uLCBOQVIsVG1lYW4sUHBtLEV4cGVyaW1lbnRJRCxJRCkNCiAjZHBseXI6OmZpbHRlcihDb2xsZWN0aW9uPT1DKCIyMDAwXzIwMDIiLCIxOTk3XzIwMDEiLCIyMDE0XzIwMTgiLCIyMDAyXzIwMDQiKSkNCkxBUi5ORVckQ29sbGVjdGlvbg0KDQpsbV9lcW4gPC0gZnVuY3Rpb24oTEFSLk5FVyl7DQogIG0gPC0gbG0oTkFSIH4gVG1lYW4sIExBUi5ORVcpOw0KICBlcSA8LSBzdWJzdGl0dXRlKGl0YWxpYyh5KSA9PSBUbWVhbiArIE5BUiAlLiUgaXRhbGljKFRtZWFuKSoiLCJ+fml0YWxpYyhSKV4yfiI9In5yMiwgDQogICAgICAgICAgICAgICAgICAgbGlzdChUbWVhbiA9IGZvcm1hdChjb2VmKG0pWzFdLCBkaWdpdHMgPSAyKSwgDQogICAgICAgICAgICAgICAgICAgICAgICBOQVIgPSBmb3JtYXQoY29lZihtKVsyXSwgZGlnaXRzID0gMiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgcjIgPSBmb3JtYXQoc3VtbWFyeShtKSRyLnNxdWFyZWQsIGRpZ2l0cyA9IDMpKSkNCiAgYXMuY2hhcmFjdGVyKGFzLmV4cHJlc3Npb24oZXEpKTsgICAgICAgICAgICAgICAgIA0KfQ0KDQoNCmVxbnMgPC0gZGRwbHkoTEFSLk5FVywuKEV4cGVyaW1lbnRJRCksbG1fZXFuKQ0KI2RmMiA8LSBkYXRhLmZyYW1lKGVxID0gdW5jbGFzcyhlcW5zKSwgQ29sbGVjdGlvbiA9IGFzLm51bWVyaWMobmFtZXMoZXFucykpKQ0KDQoNCmE8LWdncGxvdChMQVIuTkVXLCBhZXMoeD1UbWVhbiwgeT1OQVIpKSsNCiAgZ2VvbV9wb2ludCgpK3RoZW1lX2J3KCkreGxhYigiTWVhbiBhaXIgdGVtcGVyYXR1cmUgKLBDKSIpKw0KICBnZW9tX3RleHQoZGF0YSA9IGVxbnMsIGFlcyh4ID0gMTMsIHkgPSAwLjQ4LCBsYWJlbCA9IFYxKSwgc2l6ZT00LjcsDQogICAgICAgICAgY29sb3IgPSAnYmxhY2snLCAgcGFyc2UgPSBUUlVFKSsNCiB5bGFiKGJxdW90ZShib2xkKCdOb2RlIGFwcGVhcmFuY2UgcmF0ZSAoJypub2RlfmRheV4tMSonKScpKSkrDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9Yyg1LDIwKSkrDQogIGZhY2V0X3dyYXAofkV4cGVyaW1lbnRJRCkrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSwgbGluZXR5cGUgPSAxLCBjb2xvdXI9ImRhcmtncmV5IikrDQogICNyZW1vdmUgZ3JpZCBsaW5lcyANCiAgIHRoZW1lKA0KICAgICBwYW5lbC5zcGFjaW5nPXVuaXQoLjAxLCAibGluZXMiKSwNCiAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsc2l6ZT0xKSwgDQogICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siLHNpemUgPSAxKSwNCiAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0KSwNCiAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0KSwNCiAgICAgYXhpcy50aXRsZS54PWVsZW1lbnRfdGV4dChmYWNlPSJib2xkIixjb2xvdXI9ImJsYWNrIixzaXplID0gMTQpLA0KICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxNCksDQogICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIiwgZmlsbCA9ICJ3aGl0ZSIsc2l6ZT0xKSwNCiAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGFuZ2xlPTAsIGZhY2UgPSAicGxhaW4iKSwgDQogICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBmYWNlPSJwbGFpbiIpLA0KICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIsIHNpemU9MTQsIGZhY2U9ImJvbGQiKSkNCiAgICAjZ2dzYXZlKCJEOi9SL1BpY3R1cmVzL05vZGUvTm9kZSBhcHBhcmVuY2UgcmF0ZS5wbmciLCB3aWR0aD04LCBoZWlnaHQ9NiwgZHBpPTUwMCkNCmENCmRldGFjaChwYWNrYWdlOnBseXIpDQpgYGANCg0KDQoNCmBgYHtyfQ0KTEFSMg0KICAjZHBseXI6OmZpbHRlcihSb3RhdGlvbiE9IjYifENvbGxlY3Rpb24hPSIxOTk3XzIwMDEiKQ0KTEFSMi5sbT1sbShzbG9wZX5UbWVhbixkYXRhPUxBUjIpDQpzdW1tYXJ5KExBUjIubG0pDQpwcmVkaWN0KExBUjIubG0sIExBUjIsIGludGVydmFsPSJwcmVkaWN0IikNCmBgYA0KDQoNCmBgYHtyfQ0KDQojIExBUnM8LUxBUjElPiUNCiMgICBkcGx5cjo6ZmlsdGVyKENvbGxlY3Rpb249PSIyMDE0XzIwMTgiKQ0KIyANCiMgTEFSLmxtID0gbG0oT2JzZXJ2ZWQgfiBUVFMyLCBkYXRhPUxBUnMpIA0KIyBMQVIucmVzID0gcmVzaWQoTEFSLmxtKQ0KIyANCiMgDQojIHBsb3QoTEFScyRDbG9jay5Ub2RheSwgTEFSLnJlcywgeWxhYj0iUmVzaWR1YWxzIiwgeGxhYj0iRGF0ZSIpIA0KIyBhYmxpbmUoMCwgMCkgDQoNCmBgYA0KDQoNCiNsb2FkIFJvdGF0aW9uIGFuZCBHcm93dGggc2Vhc29uDQpgYGB7cixmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD04fQ0KbGlicmFyeShwbHlyKQ0KcGh5bGwgPC0gIkQ6XFxSXFwiDQpTdGFydEdyYXppbmcgPC0gcmVhZC50YWJsZShwYXN0ZTAocGh5bGwsICJFeHBlcmltZW50TGlzdC50eHQiKSwgDQogICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSkNClN0YXJ0R3JhemluZzE8LVN0YXJ0R3JhemluZyAlPiUNCiAgbXV0YXRlKEdyb3d0aFJvdGF0aW9uPSBhcy5mYWN0b3IocGFzdGUwKEdyb3d0aFNlYXNvbixSb3RhdGlvbikpKQ0KUGh5UHA8LSBtZXJnZShTdGFydEdyYXppbmcxLG1lcmdlUCxieT1jKCJOYW1lIiwiQ29sbGVjdGlvbiIsIkdyb3d0aFJvdGF0aW9uIikpDQoNCmxtX2VxbjEgPC0gZnVuY3Rpb24oUGh5UHApew0KICBtIDwtIGxtKFBoeWxsb35QcG0gLCBQaHlQcCk7DQogIGVxIDwtIHN1YnN0aXR1dGUoaXRhbGljKHkpID09IFBwbSArIFBoeWxsbyAlLiUgaXRhbGljKFBwbSkqIiwifn5pdGFsaWMoUileMn4iPSJ+cjIsIA0KICAgICAgICAgICAgICAgICAgIGxpc3QoUHBtID0gZm9ybWF0KGNvZWYobSlbMV0sIGRpZ2l0cyA9IDIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgIFBoeWxsbyA9IGZvcm1hdChjb2VmKG0pWzJdLCBkaWdpdHMgPSAyKSwgDQogICAgICAgICAgICAgICAgICAgICAgICByMiA9IGZvcm1hdChzdW1tYXJ5KG0pJHIuc3F1YXJlZCwgZGlnaXRzID0gMykpKQ0KICBhcy5jaGFyYWN0ZXIoYXMuZXhwcmVzc2lvbihlcSkpOyAgICAgICAgICAgICAgICAgDQp9DQoNCg0KZXFzIDwtIGRkcGx5KFBoeVBwLC4oVHJlbmQsU3RhZ2UpLGxtX2VxbjEpDQojZGYyIDwtIGRhdGEuZnJhbWUoZXEgPSB1bmNsYXNzKGVxbnMpLCBDb2xsZWN0aW9uID0gYXMubnVtZXJpYyhuYW1lcyhlcW5zKSkpDQojeWxhYihicXVvdGUoYm9sZCgnTEVBUiAoJyptXjJ+bV4tMn4nsENkJ14tMSonKScpKSkNCg0KUGh5UHANCm1lcmdlUA0KDQpQaHlQcCU+JQ0KICAjZHBseXI6OmZpbHRlcihSb3RhdGlvbiE9IjEiKSU+JQ0KICAjZHBseXI6OmZpbHRlcihSb3RhdGlvbiE9IjciKSU+JQ0KICAjZHBseXI6OmZpbHRlcihOYW1lIT0iSXZlcnNlbl84V2F0ZXJpcnIifEdyb3d0aFNlYXNvbiE9IjMiKSU+JQ0KICAjZHBseXI6OmZpbHRlcihTdGFnZSE9IlNlZWRsaW5nIiklPiUNCiAgZHBseXI6OmZpbHRlcihQaHlsbG9UYj09IlBoeWxsb0JyMSIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29sbGVjdGlvbiE9IjIwMTBfMjAxMiIpJT4lDQogIGdncGxvdChhZXMoeD1QcG0sIHk9UGh5bGxvLGxhYmVsPUdyb3d0aFJvdGF0aW9uLGNvbG9yPUlEKSkrZ2VvbV90ZXh0KCkrdGhlbWVfYncoKSt4bGFiKCJNZWFuIHBob3RvcGVyaW9kIChoKSIpK3lsYWIoYnF1b3RlKGJvbGQoJ1BoeWxsb2Nocm9uICgnKiewQ2QnfidtYWluIG5vZGUnXi0xKicpJykpKSsNCiAgZ2VvbV90ZXh0KGRhdGEgPSBlcXMsIGFlcyh4ID0xMywgeSA9IDc4LCBsYWJlbCA9IFYxKSwgDQogICAgICAgICAgY29sb3IgPSAnYmxhY2snLCAgcGFyc2UgPSBUUlVFKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBsaW5ldHlwZSA9IDEsIGNvbG91cj0iZGFya2dyZXkiKSsNCiAgZmFjZXRfZ3JpZChUcmVuZH5TdGFnZSkrDQogICNmYWNldF93cmFwKH5TdGFnZSxuY29sID0gMikrDQogICNnZW9tX3BvaW50KHNpemU9MikrDQogICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDcwLCBieSA9MjApLCBsaW1pdHM9YygwLDc4KSkrDQogIG15dGhlbWUzK3RoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkNCiAjZ2dzYXZlKCJEOi9SL1BpY3R1cmVzL05vZGUvcGh5bGwucG5nIiwgd2lkdGg9OCwgaGVpZ2h0PTYsIGRwaT01MDApDQogICBkZXRhY2gocGFja2FnZTpwbHlyKQ0KYGBgDQojbG9hZCBSb3RhdGlvbiBhbmQgR3Jvd3RoIHNlYXNvbiBmb3IgcG9zdGVyDQpgYGB7cixmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD04fQ0KbGlicmFyeShwbHlyKQ0KcGh5bGwgPC0gIkQ6XFxSXFwiDQpTdGFydEdyYXppbmcgPC0gcmVhZC50YWJsZShwYXN0ZTAocGh5bGwsICJFeHBlcmltZW50TGlzdC50eHQiKSwgDQogICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSkNClN0YXJ0R3JhemluZzE8LVN0YXJ0R3JhemluZyAlPiUNCiAgbXV0YXRlKEdyb3d0aFJvdGF0aW9uPSBhcy5mYWN0b3IocGFzdGUwKEdyb3d0aFNlYXNvbixSb3RhdGlvbikpKQ0KUGh5UHA8LSBtZXJnZShTdGFydEdyYXppbmcxLG1lcmdlUCxieT1jKCJOYW1lIiwiQ29sbGVjdGlvbiIsIkdyb3d0aFJvdGF0aW9uIikpDQoNCmxtX2VxbjEgPC0gZnVuY3Rpb24oUGh5UHApew0KICBtIDwtIGxtKFBoeWxsb35QcG0gLCBQaHlQcCk7DQogIGVxIDwtIHN1YnN0aXR1dGUoaXRhbGljKHkpID09IFBwbSArIFBoeWxsbyAlLiUgaXRhbGljKFBwbSkqIiwifn5pdGFsaWMoUileMn4iPSJ+cjIsIA0KICAgICAgICAgICAgICAgICAgIGxpc3QoUHBtID0gZm9ybWF0KGNvZWYobSlbMV0sIGRpZ2l0cyA9IDIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgIFBoeWxsbyA9IGZvcm1hdChjb2VmKG0pWzJdLCBkaWdpdHMgPSAyKSwgDQogICAgICAgICAgICAgICAgICAgICAgICByMiA9IGZvcm1hdChzdW1tYXJ5KG0pJHIuc3F1YXJlZCwgZGlnaXRzID0gMykpKQ0KICBhcy5jaGFyYWN0ZXIoYXMuZXhwcmVzc2lvbihlcSkpOyAgICAgICAgICAgICAgICAgDQp9DQoNCg0KZXFzIDwtIGRkcGx5KFBoeVBwLC4oVHJlbmQsU3RhZ2UpLGxtX2VxbjEpDQojZGYyIDwtIGRhdGEuZnJhbWUoZXEgPSB1bmNsYXNzKGVxbnMpLCBDb2xsZWN0aW9uID0gYXMubnVtZXJpYyhuYW1lcyhlcW5zKSkpDQojeWxhYihicXVvdGUoYm9sZCgnTEVBUiAoJyptXjJ+bV4tMn4nsENkJ14tMSonKScpKSkNCg0KUGh5UHANCm1lcmdlUA0KDQpQaHlQcCU+JQ0KICAjZHBseXI6OmZpbHRlcihSb3RhdGlvbiE9IjEiKSU+JQ0KICAjZHBseXI6OmZpbHRlcihSb3RhdGlvbiE9IjciKSU+JQ0KICAjZHBseXI6OmZpbHRlcihOYW1lIT0iSXZlcnNlbl84V2F0ZXJpcnIifEdyb3d0aFNlYXNvbiE9IjMiKSU+JQ0KICAjZHBseXI6OmZpbHRlcihTdGFnZSE9IlNlZWRsaW5nIiklPiUNCiAgZHBseXI6OmZpbHRlcihQaHlsbG9UYj09IlBoeWxsb0JyMSIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29sbGVjdGlvbiE9IjIwMTBfMjAxMiIpJT4lDQogIGdncGxvdChhZXMoeD1QcG0sIHk9UGh5bGxvLGxhYmVsPUdyb3d0aFJvdGF0aW9uLGNvbG9yPUlEKSkrZ2VvbV90ZXh0KCkrdGhlbWVfYncoKSt4bGFiKCJNZWFuIHBob3RvcGVyaW9kIChoKSIpK3lsYWIoYnF1b3RlKGJvbGQoJ1BoeWxsb2Nocm9uICgnKiewQ2QnfidtYWluIG5vZGUnXi0xKicpJykpKSsNCiAgZ2VvbV90ZXh0KGRhdGEgPSBlcXMsIGFlcyh4ID0xMywgeSA9IDc4LCBsYWJlbCA9IFYxKSwgDQogICAgICAgICAgY29sb3IgPSAnYmxhY2snLCAgcGFyc2UgPSBUUlVFKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBsaW5ldHlwZSA9IDEsIGNvbG91cj0iZGFya2dyZXkiKSsNCiAgZmFjZXRfZ3JpZChUcmVuZH5TdGFnZSkrDQogICNmYWNldF93cmFwKH5TdGFnZSxuY29sID0gMikrDQogICNnZW9tX3BvaW50KHNpemU9MikrDQogICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDcwLCBieSA9MjApLCBsaW1pdHM9YygwLDc4KSkrDQogIG15dGhlbWUzK3RoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkNCiAjZ2dzYXZlKCJEOi9SL1BpY3R1cmVzL05vZGUvcGh5bGwucG5nIiwgd2lkdGg9OCwgaGVpZ2h0PTYsIGRwaT01MDApDQogICBkZXRhY2gocGFja2FnZTpwbHlyKQ0KYGBgDQoNCg0KDQoNCmBgYHtyfQ0KUGh5UHBEPC1QaHlQcCU+JQ0KICBkcGx5cjo6ZmlsdGVyKFN0YWdlPT0iUmVncm93dGgiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKFRyZW5kPT0iRGVjIikNCm1vZDwtbG0oUGh5UHBEJFBoeWxsb35QaHlQcEQkUHBtKQ0Kc3VtbWFyeShtb2QpDQoNClBoeVBwSTwtUGh5UHAlPiUNCiAgZHBseXI6OmZpbHRlcihTdGFnZT09IlJlZ3Jvd3RoIiklPiUNCiAgZHBseXI6OmZpbHRlcihUcmVuZCE9IkRlYyIpDQptb2Q8LWxtKFBoeVBwSSRQaHlsbG9+UGh5UHBJJFBwbSkNCnN1bW1hcnkobW9kKQ0KYGBgDQoNCg0KDQoNCiMjIERlZmluZSBzdGF0cyBmdW5jdGlvbg0KDQoqIFVzaW5nIEdhdWNoIGV0IGFsLiAyMDAzIChNb2RlbCBldmFsdWF0aW9uIGJ5IGNvbXBhcmlzb24gb2YgbW9kZWwtYmFzZWQgcHJlZGljdGlvbnMgYW5kIG1lYXN1cmVkIHZhbHVlcy4gQWdyb24uIEouIDk1LCAxNDQyLTE0NDYpIA0KYGBge3IgU3RhdHMsIGluY2x1ZGUgPSBUUlVFLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04fQ0KDQojICMgUjINCiMgdGVzdERGIDwtIGRhdGEuZnJhbWUoYT1jKDEsMiwzLDQsNSksIGI9YygxMCwyMCwxMCw0MCw1MCkpDQojIA0KIyBteVIyIDwtIGZ1bmN0aW9uKHAsbykgew0KIyAgcmV0dXJuKHN1bW1hcnkobG0ocH5vLCBuYS5hY3Rpb249bmEuZXhjbHVkZSkpJHIuc3F1YXJlZCkgDQojIH0NCiMgDQojIHRlc3RERiAlPiUNCiMgICBzdW1tYXJpc2UodGhpc1IyID0gbXlSMihhLGIpKQ0KDQojIGdhdWNoIE1TRSBjb21wb25lbnRzDQpnYXVjaFN0YXRzIDwtIGZ1bmN0aW9uKHNpbSwgbWVhcykgew0KDQogIG5fcyA8LSBsZW5ndGgoc2ltKQ0KICBuX20gPC0gbGVuZ3RoKG1lYXMpDQogIG1vZGVsIDwtIGxtKG1lYXN+c2ltKQ0KICBzaW1fc3EgPC0gc3VtKChzaW0gLSBtZWFuKHNpbSkpXjIpDQogIG1lc19zcSA8LSBzdW0oKG1lYXMgLSBtZWFuKG1lYXMpKV4yKQ0KICByMiA8LSBzdW1tYXJ5KG1vZGVsKSRyLnNxdWFyZWQNCiAgc2xvcGUgPC0gbW9kZWwkY29lZmZpY2llbnRzW1syXV0NCg0KICBzYiA8LSAoc3VtKG1lYW4obWVhcykpIC0gc3VtKG1lYW4oc2ltKSkpXjINCiAgbnUgPC0gKDEtc2xvcGUpXjIgKiAoc2ltX3NxL25fcykNCiAgbGMgPC0gKDEtcjIpICogKG1lc19zcS9uX20pDQogIG1zZCA8LSBzYitudStsYw0KDQogIHNiX3IgPC0gcm91bmQoKHNiL21zZCkqMTAwLDEpDQogIG51X3IgPC0gcm91bmQoKG51L21zZCkqMTAwLDEpDQogIGxjX3IgPC0gcm91bmQoKGxjL21zZCkqMTAwLDEpDQoNCiAgbXNkX3IgPC0gc2JfcitudV9yK2xjX3INCg0KICAjIHNlbGVjdCB3aGljaCB2YXJpYWJsZXMgdG8gb3V0cHV0DQogIG91dCA8LSBjKHNiX3IsbnVfcixsY19yLCBtc2Rfciwgcm91bmQocjIqMTAwLDEpKQ0KDQogIHJldHVybihvdXQpDQoNCn0NCmBgYA0KDQojIyBUZXN0IHN0YXRzIGZ1bmN0aW9ucyB1c2VkDQoNCmBgYHtyfQ0KcyA8LSBjKDQyMzEuOTcyLDM5MzUuNjA0LDM3NzkuNjUyLDM2MjcuNjg3LDMzNjMuNDk5LDMyMzAuNTY2LDI4NjguMTE0LDI4NjguODI3KQ0KbSA8LSBjKDQ5ODcuNjYsNTYzNi4wOSw0NzU0LjA2LDQxMTQuNTMsNDE0MS43MiwzNzA0LjA2LDUxNDIuMTksNDc2Mi4wMykNCg0KeCA8LSBnYXVjaFN0YXRzKHMsbSkNCg0KdGVtcERmIDwtIGRhdGEuZnJhbWUoc3RhdE5hbWU9YygiU0IiLCJOVSIsIkxDIiwicl9NU0QiLCJSMiIpLCBzdGF0VmFsdWU9eCkNCiMga2FibGUodGVtcERmLCBkaWdpdHM9IDIpDQp0ZW1wRGYyIDwtIGRhdGEuZnJhbWUoUHJlZGljdGVkPXMsIE9ic2VydmVkPW0pDQoNCnggPC0gdGVtcERmMiAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG4gPSBuKCksDQogICAgcjIgPSBnYXVjaFN0YXRzKFByZWRpY3RlZCxPYnNlcnZlZClbNV0sDQogICMgIHJtc2UgPSByb3VuZChybXNlKFByZWRpY3RlZCxPYnNlcnZlZCksMCksDQogICAgcl9ybXNlID0gcm91bmQocm1zZShQcmVkaWN0ZWQsT2JzZXJ2ZWQpL21lYW4oT2JzZXJ2ZWQpKjEwMCwxKSwNCiAgICBuc2UgPSByb3VuZChOU0UoUHJlZGljdGVkLE9ic2VydmVkKSwxKSwNCiAgICBzYiA9IGdhdWNoU3RhdHMoUHJlZGljdGVkLE9ic2VydmVkKVsxXSwNCiAgbnUgPSBnYXVjaFN0YXRzKFByZWRpY3RlZCxPYnNlcnZlZClbMl0sDQogIGxjID0gZ2F1Y2hTdGF0cyhQcmVkaWN0ZWQsT2JzZXJ2ZWQpWzNdDQogICkgJT4lIA0KICB0KCkgDQoNCmRmIDwtIGRhdGEuZnJhbWUoc3RhdCA9IHJvdy5uYW1lcyh4KSxzdGF0dmFsdWUgPSB4WywxXSkNCg0KZGYgJT4lDQogIGthYmxlKGZvcm1hdCA9ICJtYXJrZG93biIpDQpgYGANCiMjIExvYWQgc2ltdWxhdGVkIGRhdGFiYXNlDQojIyBjcmVhdGUgZnVuY3Rpb24gdG8gcmVhZCBkYXRhIChKdXN0aW4ncyBzY3JpcHQpDQpgYGB7ciBMb2FkU2ltLCBpbmNsdWRlID0gRkFMU0UsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTh9DQpHZXRBcHNpbU5HVGFibGUgPC0gZnVuY3Rpb24oZGJMb2MsIHRhYmxlKSANCnsNCiAgY29ubmVjdGlvbiA8LSBkYkNvbm5lY3QoU1FMaXRlKCksIGRibmFtZSA9IGRiTG9jLCBmbGFncyA9IFNRTElURV9SVykNCiAgdGFibGUgPC0gZGJSZWFkVGFibGUoY29ubmVjdGlvbiwgdGFibGUsIHJvdy5uYW1lcz1OVUxMKQ0KICBkYkRpc2Nvbm5lY3QoY29ubmVjdGlvbikNCiAgcmV0dXJuKHRhYmxlKQ0KfQ0KDQpgYGANCiMgbG9hZCBhZGRyZXNzIG9mIGRiDQojIHNldCB0YWJsZSB0byBiZSBlbnF1aWVyZA0KIyBsb2FkIHRhYmxlIGludG8gYW4gb2JqZWN0DQojIG1ha2UgaXQgYSBkYXRhZnJhbWUNCiMgY2hhbmdlIGRhdGUgdG8gY29yZXJjdCBmb3JtYXQgDQojIGV4cGxvcmUgdGhlIGRmDQpgYGB7cn0NCmRiLmFkZHJlc3MgPC0gIkQ6XFxBUFNJTVgyXFxQcm90b3R5cGVzXFxMdWNlcm5lXFxMdWNlcm5lVmFsaWRhdGlvbi5kYiINCnRhYmxlTmFtZTwtIlJlcG9ydCINCkRiVGFibGUgPC0gR2V0QXBzaW1OR1RhYmxlKGRiLmFkZHJlc3MsdGFibGVOYW1lKQ0KZGYgPC0gYXMuZGF0YS5mcmFtZShEYlRhYmxlKQ0KZGYkQ2xvY2suVG9kYXkgPC0geW1kX2htcyhkZiRDbG9jay5Ub2RheSkNCnN0cihkZikNCnN1bW1hcnkoZGYpDQpoZWFkKGRmKSAjIHNpbXVsYXRpb24gcmVzdWx0cw0KYGBgDQojIGdldCBzaW0gbmFtZXMgKGRpZmZlcmVudCB0YWJsZSkNCiMgbWVyZ2UgbmFtZXMgDQojIHJlbW92ZSB1bmVjZXNzYXJ5IHZhcmlhYmxlcw0KYGBge3J9DQpzaW1OYW1lRGYgPC0gYXMuZGF0YS5mcmFtZSAoR2V0QXBzaW1OR1RhYmxlKGRiLmFkZHJlc3MsIl9TaW11bGF0aW9ucyIpKQ0KbXlEYiA8LSBtZXJnZShkZiwgc2ltTmFtZURmLCBieS54PSBjKCJTaW11bGF0aW9uSUQiKSwgYnkueT0gYygiSUQiKSkNCg0KDQojc3RyKG15RGIpDQpoZWFkKG15RGIpDQpzdW1tYXJ5KG15RGIpDQoNCiMgbXlEYiAlPiUNCiMgICBkcGx5cjo6c2VsZWN0KE5hbWUpICU+JQ0KIyAgIHVuaXF1ZSgpDQoNCmBgYA0KIyMgUHJlcGFyZSBtZXJnZQ0KIyMgQWRkIGluZm8gZm9yIG1lcmdpbmcNCiMjIHNlbGVjdCB2YXJpYWJsZXMgdGhhdCBhcmUgZm9yIGNvbXBhcmluZyB3aXRoIG9ic2VydmVkIGRhdGENCg0KYGBge3J9DQpzaW1EIDwtIG15RGIgJT4lDQogIGRwbHlyOjpzZWxlY3QoTmFtZSxDbG9jay5Ub2RheSxMQUksU1dDLEhlaWdodCxzaG9vdGJpb21hc3MsUm9vdFd0LCBTdGVtV3QsIExlYWZXdCxOb2RlTnVtYmVyKSAlPiUNCiAgdGlkeXI6OmdhdGhlcigiVmFyaWFibGUiLCJQcmVkaWN0ZWQiLExBSTpOb2RlTnVtYmVyKSAlPiUNCiAgbXV0YXRlKE5hbWUgPSBhcy5mYWN0b3IoTmFtZSkpICU+JQ0KICBtdXRhdGUoVmFyaWFibGUgPSBhcy5mYWN0b3IoVmFyaWFibGUpKSAlPiUNCiAgbXV0YXRlKENsb2NrLlRvZGF5ID0geW1kX2htcyhDbG9jay5Ub2RheSkpDQoNCmhlYWQoc2ltRCkNCnN1bW1hcnkoc2ltRCkNCg0KDQpoZWFkKG9ic05vZGUpDQptZXJnZWRmPC1tZXJnZShvYnNBLHNpbUQsYnk9YygiQ2xvY2suVG9kYXkiLCJOYW1lIiwiVmFyaWFibGUiKSkNCnN1bW1hcnkobWVyZ2VkZikNCnN0cihtZXJnZWRmKQ0KbWVyZ2VkZg0KDQpgYGANCg0KDQojIyBOb2RlIG51bWJlcg0KI1RpbWUgc2VyaWVzDQojIyBvYnMgVnMgUHJlIGZvciBlYWNoIGV4cGVyaW1lbnQNCiMjIDE5OTctMjAwMQ0KYGBge3IsZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OX0NCg0Kb2JzTm9kZTE8LW9ic0ElPiUNCiAgZHBseXI6OmZpbHRlcihDb2xsZWN0aW9uPT0iMTk5N18yMDAxIiklPiUNCiAgZHBseXI6OmZpbHRlcihWYXJpYWJsZT09Ik5vZGVOdW1iZXIiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKE5hbWU9PSJJdmVyc2VuXzhXYXRlcmlyciIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ2xvY2suVG9kYXk+IjE5OTctMDgtMDEiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKENsb2NrLlRvZGF5PCIyMDAxLTA4LTAxIikNCiAgDQogIA0KICAgDQogc2ltRDE8LXNpbUQlPiUNCiAgIG11dGF0ZShDbG9jay5Ub2RheSA9IHltZF9obXMoQ2xvY2suVG9kYXkpKSU+JQ0KICAgZHBseXI6OmZpbHRlcihDbG9jay5Ub2RheT4iMTk5Ny0wOC0wMSIpJT4lDQogICBkcGx5cjo6ZmlsdGVyKENsb2NrLlRvZGF5PCIyMDAxLTA4LTAxIiklPiUNCiAgIGRwbHlyOjpmaWx0ZXIoVmFyaWFibGU9PSJOb2RlTnVtYmVyIiklPiUNCiAgIGRwbHlyOjpmaWx0ZXIoTmFtZT09Ikl2ZXJzZW5fOFdhdGVyaXJyIikNCiBzdHIoc2ltRDEpDQogc2ltRDElPiUNCiBnZ3Bsb3QoYWVzKHg9Q2xvY2suVG9kYXkseT1QcmVkaWN0ZWQpKStnZW9tX2xpbmUoc2l6ZT0xKSt0aGVtZV9idygpKw0KIGZhY2V0X3dyYXAofklELG5jb2wgPSAyKSsNCiBnZW9tX3BvaW50KGRhdGE9b2JzTm9kZTEsIGFlcyh4PUNsb2NrLlRvZGF5MSwgeT1PYnNlcnZlZCksY29sb3VyPSJncmVlbiIsc2l6ZT0zKSsNCiB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLGxlZ2VuZC5wb3NpdGlvbiA9ICJibGFuayIpK3hsYWIoIkRhdGUiKSt5bGFiKCJOb2RlIG51bWJlciIpKw0KICAgICNyZW1vdmUgZ3JpZCBsaW5lcyANCiAgdGhlbWUoDQogICAgIHBhbmVsLnNwYWNpbmc9dW5pdCguMDEsICJsaW5lcyIpLA0KICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIixzaXplPTEpLCANCiAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIsc2l6ZSA9IDEpLA0KICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMTQsIHZqdXN0PTAuNSwgaGp1c3QgPSAxKSwNCiAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0KSwNCiAgICAgYXhpcy50aXRsZS54PWVsZW1lbnRfdGV4dChmYWNlPSJib2xkIixjb2xvdXI9ImJsYWNrIixzaXplID0gMTQpLA0KICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxNCksDQogICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIiwgZmlsbCA9ICJ3aGl0ZSIsc2l6ZT0xKSwNCiAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGFuZ2xlPTAsIGZhY2UgPSAicGxhaW4iKSwgDQogICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBmYWNlPSJwbGFpbiIpLA0KICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIsIHNpemU9MTQsIGZhY2U9ImJvbGQiKSwNCiAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHZqdXN0ID0gMC41LCBzaXplID0gMTQpKSsNCiAgIGFubm90YXRlKCJ0ZXh0IiwgeD15bWRfaG1zKCIxOTk5LTEwLTI0IDEyOjAwOjAwIiksIHk9MTcsIHNpemUgPSA1LCBsYWJlbCA9InBhc3RlKFJfUk1TRCA9PSAyMS44LCclJykiLCBwYXJzZT1UKQ0KICNnZ3NhdmUoIkQ6L1IvUGljdHVyZXMvTm9kZS9JdmVyc2VuXzhXYXRlcmlycm5vZGVudW1iZXIucG5nIiwgd2lkdGg9OCwgaGVpZ2h0PTQsIGRwaT01MDApDQoNCmBgYA0KDQoNCiMjMjAwMi0yMDA0DQpgYGB7ciwgIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTh9DQpvYnNOb2RlMjwtb2JzTm9kZSU+JSANCiAgZHBseXI6OmZpbHRlcihDb2xsZWN0aW9uPT0iMjAwMl8yMDA0IiklPiUNCiAgZHBseXI6OmZpbHRlcihWYXJpYWJsZT09Ik5vZGVOdW1iZXIiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKE5hbWU9PSJJdmVyc2VuXzkxRGVmb2xpYXRpb25MTCIpDQoNCnNpbUQyPC1zaW1EJT4lDQogIG11dGF0ZShDbG9jay5Ub2RheSA9IHltZF9obXMoQ2xvY2suVG9kYXkpKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKENsb2NrLlRvZGF5PiIyMDAyLTA2LTAxIiklPiUNCiAgZHBseXI6OmZpbHRlcihWYXJpYWJsZT09Ik5vZGVOdW1iZXIiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKE5hbWU9PSJJdmVyc2VuXzkxRGVmb2xpYXRpb25MTCIpDQpzdHIoc2ltRDIpDQpzaW1EMiU+JQ0KZ2dwbG90KGFlcyh4PUNsb2NrLlRvZGF5LHk9UHJlZGljdGVkKSkrZ2VvbV9saW5lKHNpemU9MSkrdGhlbWVfYncoKSsNCiAgI2ZhY2V0X3dyYXAofklELG5jb2wgPSAxKSsNCiAgZ2VvbV9wb2ludChkYXRhPW9ic05vZGUyLCBhZXMoeD1DbG9jay5Ub2RheTEsIHk9T2JzZXJ2ZWQpLGNvbG91cj0iYmx1ZSIsc2l6ZT0zKSsNCiAgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSxsZWdlbmQucG9zaXRpb24gPSAiYmxhbmsiKSt4bGFiKCJEYXRlIikreWxhYigiTm9kZSBudW1iZXIiKSsNCiAgI3JlbW92ZSBncmlkIGxpbmVzIA0KICB0aGVtZSgNCiAgICAgcGFuZWwuc3BhY2luZz11bml0KC4wMSwgImxpbmVzIiksDQogICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLHNpemU9MSksIA0KICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIixzaXplID0gMSksDQogICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAxNCwgdmp1c3Q9MC41LCBoanVzdCA9IDEpLA0KICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMTQpLA0KICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxNCksDQogICAgIGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDE0KSwNCiAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gIndoaXRlIixzaXplPTEpLA0KICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgYW5nbGU9MCwgZmFjZSA9ICJwbGFpbiIpLCANCiAgICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGZhY2U9InBsYWluIiksDQogICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIiwgc2l6ZT0xNCwgZmFjZT0iYm9sZCIpLA0KICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgdmp1c3QgPSAwLjUsIHNpemUgPSAxNCkpKw0KICBhbm5vdGF0ZSgidGV4dCIsIHg9eW1kX2htcygiMjAwMy0wNy0yNCAxMjowMDowMCIpLCB5PTE3LCBzaXplID0gNSwgbGFiZWwgPSJwYXN0ZShSX1JNU0QgPT0gMjEuOSwnJScpIiwgcGFyc2U9VCkNCiAgICNnZ3NhdmUoIkQ6L1IvUGljdHVyZXMvTm9kZS9JdmVyc2VuXzkxRGVmb2xpYXRpb25MTG5vZGVudW1iZXIucG5nIiwgd2lkdGg9OCwgaGVpZ2h0PTQsIGRwaT01MDApDQogIGdnc2F2ZSgiRDovUi9QaWN0dXJlcy9Qb3N0ZXIvRTMucG5nIiwgd2lkdGg9OCwgaGVpZ2h0PTQsIGRwaT01MDApDQogIA0KDQoNCmBgYA0KDQoNCg0KIyMyMDAwLTIwMDINCmBgYHtyLCAgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OH0NCm9ic05vZGUzPC1vYnNOb2RlJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29sbGVjdGlvbj09IjIwMDBfMjAwMiIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoVmFyaWFibGU9PSJOb2RlTnVtYmVyIikNCiBvYnNOb2RlMyANCg0Kc2ltRDNhPC1zaW1EJT4lDQogIG11dGF0ZShDbG9jay5Ub2RheSA9IHltZF9obXMoQ2xvY2suVG9kYXkpKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKENsb2NrLlRvZGF5PiIyMDAwLTEwLTI0IDEyOjAwOjAwIiklPiUNCiAgZHBseXI6OmZpbHRlcihDbG9jay5Ub2RheTwiMjAwMi0wNy0wMSAxMjowMDowMCIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoTmFtZT09YygiSXZlcnNlbl85U293aW5nRGF0ZVNEMVdhdGVyaXJyIiwiSXZlcnNlbl85U293aW5nRGF0ZVNEMldhdGVyaXJyIiwiSXZlcnNlbl85U293aW5nRGF0ZVNEM1dhdGVyaXJyIiwiSXZlcnNlbl85U293aW5nRGF0ZVNENFdhdGVyaXJyIikpJT4lDQogIGRwbHlyOjpmaWx0ZXIoVmFyaWFibGU9PSJOb2RlTnVtYmVyIikNCg0KREY8LWRhdGEuZnJhbWUoTmFtZT1jKCJJdmVyc2VuXzlTb3dpbmdEYXRlU0QxV2F0ZXJpcnIiLCJJdmVyc2VuXzlTb3dpbmdEYXRlU0QyV2F0ZXJpcnIiLCJJdmVyc2VuXzlTb3dpbmdEYXRlU0QzV2F0ZXJpcnIiLCJJdmVyc2VuXzlTb3dpbmdEYXRlU0Q0V2F0ZXJpcnIiKSxJRD0gYygiRTJJTExTMSIsIkUySUxMUzIiLCJFMklMTFMzIiwiRTJJTExTNCIpKQ0Kc2ltRDM8LW1lcmdlKERGLHNpbUQzYSwgYnk9YygiTmFtZSIpKQ0KIEc8LXNpbUQzJT4lDQpnZ3Bsb3QoYWVzKHg9Q2xvY2suVG9kYXkseT1QcmVkaWN0ZWQpKStnZW9tX2xpbmUoc2l6ZT0xKSt0aGVtZV9idygpKw0KICBnZW9tX3BvaW50KGRhdGE9b2JzTm9kZTMsIGFlcyh4PUNsb2NrLlRvZGF5MSwgeT1PYnNlcnZlZCksY29sb3VyPSJncmVlbiIsc2l6ZT0zKSsNCiAgIGZhY2V0X3dyYXAofklELG5jb2wgPSAyKSsNCiAgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSxsZWdlbmQucG9zaXRpb24gPSAiYmxhbmsiKSt4bGFiKCJEYXRlIikreWxhYigiTm9kZSBudW1iZXIiKSsNCiAgdGhlbWUoDQogICAgIHBhbmVsLnNwYWNpbmc9dW5pdCguMDEsICJsaW5lcyIpLA0KICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIixzaXplPTEpLCANCiAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIsc2l6ZSA9IDEpLA0KICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMTQsIHZqdXN0PTAuNSwgaGp1c3QgPSAxKSwNCiAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0KSwNCiAgICAgYXhpcy50aXRsZS54PWVsZW1lbnRfdGV4dChmYWNlPSJib2xkIixjb2xvdXI9ImJsYWNrIixzaXplID0gMTQpLA0KICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxNCksDQogICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIiwgZmlsbCA9ICJ3aGl0ZSIsc2l6ZT0xKSwNCiAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGFuZ2xlPTAsIGZhY2UgPSAicGxhaW4iKSwgDQogICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBmYWNlPSJwbGFpbiIpLA0KICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIsIHNpemU9MTQsIGZhY2U9ImJvbGQiKSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgdmp1c3QgPSAwLjUsIHNpemUgPSAxNCkpDQoNCg0KZGF0X3RleHQxIDwtIGRhdGEuZnJhbWUoDQogIGxhYmVsID0gYygiUl9STVNFPTI3LjclIiwgIlJfUk1TRT0yOCUiLCAiUl9STVNFPTIxLjglIiwiUl9STVNFPTI0LjUlIiksDQogIElEPSBjKCJFMklMTFMxIiwiRTJJTExTMiIsIkUySUxMUzMiLCJFMklMTFM0IiksDQogIHg9IHltZF9obXMoIjIwMDEtMDMtMjQgMTI6MDA6MDAiLCAiMjAwMS0wMy0yNCAxMjowMDowMCIsIjIwMDEtMDMtMjQgMTI6MDA6MDAiLCIyMDAxLTAzLTI0IDEyOjAwOjAwIiksDQogIHk9YygxNywxNywxNywxNykpDQoNCiBHK2dlb21fdGV4dChkYXRhPWRhdF90ZXh0MSwgbWFwcGluZyA9IGFlcyh4PXgseT15LCBsYWJlbCA9IGxhYmVsKSxoanVzdCAgID0gLTAuMSx2anVzdCAgID0gLTEsc2l6ZT01KQ0KDQojZ2dzYXZlKCJEOi9SL1BpY3R1cmVzL05vZGUvSXZlcnNlbl85U293aW5nRGF0ZW5vZGVudW1iZXIucG5nIiwgd2lkdGg9OCwgaGVpZ2h0PTgsIGRwaT01MDApDQogIA0KICANCmBgYA0KIyMyMDE0LTIwMTgNCmBgYHtyLCAgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OH0NCm9ic05vZGU0PC1vYnNOb2RlJT4lIA0KICBkcGx5cjo6ZmlsdGVyKENvbGxlY3Rpb249PSIyMDE0XzIwMTgiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKFZhcmlhYmxlPT0iTm9kZU51bWJlciIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoTmFtZT09Ikl2ZXJzZW5fMTIxRGVmb2xpYXRpb25MTEZERkQ1IikNCg0Kc2ltRDRhPC1zaW1EJT4lDQogIG11dGF0ZShDbG9jay5Ub2RheSA9IHltZF9obXMoQ2xvY2suVG9kYXkpKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKFZhcmlhYmxlPT0iTm9kZU51bWJlciIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoTmFtZT09Ikl2ZXJzZW5fMTIxRGVmb2xpYXRpb25MTEZERkQ1IiklPiUNCiAgZHBseXI6OmZpbHRlcihDbG9jay5Ub2RheTwiMjAxNS0wMS0wNiIpDQoNCnNpbUQ0Yjwtc2ltRCU+JQ0KICBtdXRhdGUoQ2xvY2suVG9kYXkgPSB5bWRfaG1zKENsb2NrLlRvZGF5KSklPiUNCiAgZHBseXI6OmZpbHRlcihWYXJpYWJsZT09Ik5vZGVOdW1iZXIiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKE5hbWU9PSJJdmVyc2VuXzEyMURlZm9saWF0aW9uTExGREZENSIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ2xvY2suVG9kYXk+IjIwMTUtMDEtMzAiKQ0Kc2ltRDQ8LXJiaW5kKHNpbUQ0YSxzaW1ENGIpDQogIA0Kc3RyKHNpbUQ0KQ0Kc2ltRDQlPiUNCmdncGxvdChhZXMoeD1DbG9jay5Ub2RheSx5PVByZWRpY3RlZCkpK2dlb21fbGluZShzaXplPTEpK3RoZW1lX2J3KCkrDQogIGZhY2V0X3dyYXAofklELG5jb2wgPSAxKSsNCiAgZ2VvbV9wb2ludChkYXRhPW9ic05vZGU0LCBhZXMoeD1DbG9jay5Ub2RheTEsIHk9T2JzZXJ2ZWQpLGNvbG91cj0iZ3JlZW4iLHNpemU9MykrDQogIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCksbGVnZW5kLnBvc2l0aW9uID0gImJsYW5rIikreGxhYigiRGF0ZSIpK3lsYWIoIk5vZGUgbnVtYmVyIikrDQogICNyZW1vdmUgZ3JpZCBsaW5lcyANCiAgIHRoZW1lKA0KICAgICBwYW5lbC5zcGFjaW5nPXVuaXQoLjAxLCAibGluZXMiKSwNCiAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsc2l6ZT0xKSwgDQogICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siLHNpemUgPSAxKSwNCiAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZSA9ICJwbGFpbiIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDE0LCB2anVzdD0wLjUsIGhqdXN0ID0gMSksDQogICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAxNCksDQogICAgIGF4aXMudGl0bGUueD1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDE0KSwNCiAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfdGV4dChmYWNlPSJib2xkIixjb2xvdXI9ImJsYWNrIixzaXplID0gMTQpLA0KICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAid2hpdGUiLHNpemU9MSksDQogICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBhbmdsZT0wLCBmYWNlID0gInBsYWluIiksIA0KICAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgZmFjZT0icGxhaW4iKSwNCiAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91cj0iYmxhY2siLCBzaXplPTE0LCBmYWNlPSJib2xkIiksDQogICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCB2anVzdCA9IDAuNSwgc2l6ZSA9IDE0KSkrDQogICBhbm5vdGF0ZSgidGV4dCIsIHg9eW1kX2htcygiMjAxNi0wNy0yNCAxMjowMDowMCIpLCB5PTE4LCBzaXplID0gNSwgbGFiZWwgPSJwYXN0ZShSX1JNU0QgPT0gMzAsJyUnKSIsIHBhcnNlPVQpDQogICAjZ2dzYXZlKCJEOi9SL1BpY3R1cmVzL05vZGUvSXZlcnNlbl8xMjFEZWZvbGlhdGlvbkxMRkRGRDVub2RlbnVtYmVyLnBuZyIsIHdpZHRoPTgsIGhlaWdodD00LCBkcGk9NTAwKQ0KICANCiAgDQoNCg0KYGBgDQoNCiMgU3RhdGlzdGljIGFuZCBHcmFwaA0KYGBge3IsZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OH0NCm1lcmdlZGYNCnN1bW1hcnkobWVyZ2VkZikNCnN0cihtZXJnZWRmKQ0KDQpkPC1tZXJnZWRmICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIoVmFyaWFibGU9PSAiTm9kZU51bWJlciIpICU+JSANCiAgIGRwbHlyOjpmaWx0ZXIoV2F0ZXI9PSAiaXJyIiklPiUNCiAgZHBseXI6OmZpbHRlcihEZWZvbGlhdGlvbj09ICJMTCIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29sbGVjdGlvbiE9IjIwMTBfMjAxMiIpJT4lDQogIGdncGxvdChhZXMoeD1PYnNlcnZlZCwgeT0gUHJlZGljdGVkLCBjb2xvdXI9IGZhY3RvcihOYW1lKSkpICsNCiAgZ2VvbV9wb2ludChzaXplPTIpK3RoZW1lX2J3KCkrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSwgbGluZXR5cGUgPSAxLCBjb2xvdXI9ImRhcmtncmV5IikgKw0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsNCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSsNCiAgZ2d0aXRsZSgiTm9kZSBOdW1iZXIiKSsNCiAgZmFjZXRfd3JhcCh+SUQsIG5jb2wgPSA0KSsNCiAgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSxsZWdlbmQucG9zaXRpb24gPSAiYmxhbmsiKSt4bGFiKCJPYnNlcnZlZCIpK3lsYWIoIlByZWRpY3RlZCIpKw0KICB0aGVtZSgNCiAgICAgcGFuZWwuc3BhY2luZz11bml0KC4wMSwgImxpbmVzIiksDQogICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLHNpemU9MSksIA0KICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIixzaXplID0gMSksDQogICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAxNCwgdmp1c3Q9MC41LCBoanVzdCA9IDEpLA0KICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMTQpLA0KICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxNCksDQogICAgIGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDE0KSwNCiAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gIndoaXRlIixzaXplPTEpLA0KICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgYW5nbGU9MCwgZmFjZSA9ICJwbGFpbiIpLCANCiAgICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGZhY2U9InBsYWluIiksDQogICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIiwgc2l6ZT0xNCwgZmFjZT0iYm9sZCIpLA0KICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgdmp1c3QgPSAwLjUsIHNpemUgPSAxNCkpDQogICAjZ2dzYXZlKCJEOi9SL1BpY3R1cmVzL05vZGUvbm9kZW51bWJlci5wbmciLCB3aWR0aD04LCBoZWlnaHQ9NiwgZHBpPTUwMCkNCmBgYA0KDQpgYGB7cixmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04fQ0KIyAjIGZpdCBtb2RlbCBhbmQgZ2V0IGxvd2VyL3VwcGVyIDk1JSBjb25maWRlbmNlIGxpbWl0cyBhdCB0aGUgb2JzZXJ2ZWQgeCdzDQojIG0gPC0gbG0oeXZhbHVlcyB+IHh2YWx1ZXMsIGRhdGEgPSBkKQ0KIyBtcCA8LSBwcmVkaWN0KG0sIGludGVydmFsID0gJ2NvbmYnKQ0KIyANCiMgIyBiaW5kIHByZWRpY3Rpb25zIHRvIG9yaWdpbmFsIGRhdGEgYW5kIHBsb3QNCiMgZDIgPC0gY2JpbmQoZCwgbXApDQojIHAgPC0gZ2dwbG90KGQyLCBhZXMoeCA9IHh2YWx1ZXMsIHkgPSB5dmFsdWVzKSkNCiMgcCArIGdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScsIHNlID0gRkFMU0UpICsNCiMgICAgIGdlb21fbGluZShhZXMoeSA9IHVwciksIGNvbG9yID0gJ3JlZCcsIGxpbmV0eXBlID0gMikgKw0KIyAgICAgZ2VvbV9saW5lKGFlcyh5ID0gbHdyKSwgY29sb3IgPSAncmVkJywgbGluZXR5cGUgPSAyKSANCg0KDQptZXJnZWRmMTwtbWVyZ2VkZiU+JQ0KICBkcGx5cjo6ZmlsdGVyKFZhcmlhYmxlPT0gIk5vZGVOdW1iZXIiKSAlPiUgDQogICBkcGx5cjo6ZmlsdGVyKFdhdGVyPT0gImlyciIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoRGVmb2xpYXRpb249PSAiTEwiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbGxlY3Rpb24hPSIyMDEwXzIwMTIiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEPT1jKCJFM0lMTCIsIkU1SUxMRjUiKSkNCnN1bW1hcnkobWVyZ2VkZjEpDQpzdHIobWVyZ2VkZjEpDQptIDwtIGxtKFByZWRpY3RlZCB+IE9ic2VydmVkLCBkYXRhID0gbWVyZ2VkZjEpDQptcCA8LSBwcmVkaWN0KG0sIGludGVydmFsID0gJ2NvbmYnKQ0KZDIgPC0gY2JpbmQobWVyZ2VkZjEsIG1wKQ0KDQpwMTwtZDIgJT4lDQogICAgDQogIGdncGxvdChhZXMoeD1PYnNlcnZlZCwgeT0gUHJlZGljdGVkLGNvbG9yPUlEKSkrDQpnZW9tX3BvaW50KHNpemU9Mixjb2xvdXI9ImJsdWUiKSt0aGVtZV9idygpKyBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nLCBzZSA9IEZBTFNFLCBjb2xvcj0iYmxhY2siKSArDQogICAgZ2VvbV9saW5lKGFlcyh5ID0gdXByKSwgY29sb3IgPSAnYmxhY2snLCBsaW5ldHlwZSA9IDMsc2l6ZT0xKSArDQogICAgZ2VvbV9saW5lKGFlcyh5ID0gbHdyKSwgY29sb3IgPSAnYmxhY2snLCBsaW5ldHlwZSA9IDMsc2l6ZT0xKSsNCiAgI2dlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSwgbGluZXR5cGUgPSAzLCBjb2xvdXI9ImJsYWNrIikgKw0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsc2l6ZT0xLGNvbG9yPSJwdXJwbGUiKSArDQogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkrDQogIGdndGl0bGUoIk5vZGUgTnVtYmVyIikrDQogICNmYWNldF93cmFwKH5JRCwgbmNvbCA9IDQpKw0KICB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLGxlZ2VuZC5wb3NpdGlvbiA9ICJibGFuayIpKw0KICB4bGFiKCJPYnNlcnZlZCIpK3lsYWIoIlByZWRpY3RlZCIpKw0KICB0aGVtZSgNCiAgICAgcGFuZWwuc3BhY2luZz11bml0KC4wMSwgImxpbmVzIiksDQogICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLHNpemU9MSksIA0KICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIixzaXplID0gMSksDQogICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAxNCwgdmp1c3Q9MC41LCBoanVzdCA9IDEpLA0KICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMTQpLA0KICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxNCksDQogICAgIGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDE0KSwNCiAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gIndoaXRlIixzaXplPTEpLA0KICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgYW5nbGU9MCwgZmFjZSA9ICJwbGFpbiIpLCANCiAgICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGZhY2U9InBsYWluIiksDQogICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIiwgc2l6ZT0xNCwgZmFjZT0iYm9sZCIpLA0KICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgdmp1c3QgPSAwLjUsIHNpemUgPSAxNCkpDQogICBnZ3NhdmUoIkQ6L1IvUGljdHVyZXMvUG9zdGVyL25vZGVudW1iZXIucG5nIiwgd2lkdGg9OCwgaGVpZ2h0PTQsIGRwaT01MDApDQpgYGANCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCiMjIDIwMDItMjAwNA0KDQpgYGB7cn0NCm1lcmdlZGYNCnN1bW1hcnkobWVyZ2VkZikNCnN0cihtZXJnZWRmKQ0KDQptZXJnZWRmICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIoQ29sbGVjdGlvbj09IjIwMDJfMjAwNCIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoVmFyaWFibGU9PSAiTm9kZU51bWJlciIpICU+JSANCiAgIGRwbHlyOjpmaWx0ZXIoV2F0ZXI9PSAiaXJyIiklPiUNCiAgZHBseXI6OmZpbHRlcihEZWZvbGlhdGlvbj09ICJMTCIpJT4lDQogIGdncGxvdChhZXMoeD1PYnNlcnZlZCwgeT0gUHJlZGljdGVkLCANCiAgICAgICAgICBjb2xvdXI9IGZhY3RvcihOYW1lKSkpICsNCiAgZ2VvbV9wb2ludChzaXplPTMpK3RoZW1lX2J3KCkrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSwgbGluZXR5cGUgPSAxLCBjb2xvdXI9ImRhcmtncmV5IikgKw0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsNCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSsNCiAgZ2d0aXRsZSgiTm9kZSBOdW1iZXIiKSsNCiAgZmFjZXRfZ3JpZChHcm93dGhTZWFzb25+Um90YXRpb24pKw0KICB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLGxlZ2VuZC5wb3NpdGlvbiA9ICJibGFuayIpK3hsYWIoIk9ic2VydmVkIikreWxhYigiUHJlZGljdGVkIikrDQogIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDEyKSkrDQogIHRoZW1lKGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDEyKSkNCmBgYA0KYGBge3J9DQptZXJnZWRmICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIoQ29sbGVjdGlvbj09IjIwMTRfMjAxOCIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoVmFyaWFibGU9PSAiTm9kZU51bWJlciIpICU+JSANCiAgIGRwbHlyOjpmaWx0ZXIoV2F0ZXI9PSAiaXJyIiklPiUNCiAgZHBseXI6OmZpbHRlcihEZWZvbGlhdGlvbj09ICJMTCIpJT4lDQogIGdncGxvdChhZXMoeD1PYnNlcnZlZCwgeT0gUHJlZGljdGVkLCANCiAgICAgICAgICBjb2xvdXI9IGZhY3RvcihOYW1lKSkpICsNCiAgZ2VvbV9wb2ludChzaXplPTMpK3RoZW1lX2J3KCkrDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSwgbGluZXR5cGUgPSAxLCBjb2xvdXI9ImRhcmtncmV5IikgKw0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsNCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSsNCiAgZ2d0aXRsZSgiTm9kZSBOdW1iZXIiKSsNCiAgZmFjZXRfZ3JpZChHcm93dGhTZWFzb25+Um90YXRpb24pKw0KICB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLGxlZ2VuZC5wb3NpdGlvbiA9ICJibGFuayIpK3hsYWIoIk9ic2VydmVkIikreWxhYigiUHJlZGljdGVkIikrDQogIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDEyKSkrDQogIHRoZW1lKGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDEyKSkNCmBgYA0KDQoNCg0KIyMgMjAwMC0yMDAyDQoNCmBgYHtyfQ0KbWVyZ2VkZg0Kc3VtbWFyeShtZXJnZWRmKQ0Kc3RyKG1lcmdlZGYpDQoNCm1lcmdlZGYgJT4lDQogICAgZHBseXI6OmZpbHRlcihDb2xsZWN0aW9uPT0iMjAwMF8yMDAyIiklPiUNCiAgZHBseXI6OmZpbHRlcihWYXJpYWJsZT09ICJOb2RlTnVtYmVyIikgJT4lIA0KICAgZHBseXI6OmZpbHRlcihXYXRlcj09ICJpcnIiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKERlZm9saWF0aW9uPT0gIkxMIiklPiUNCiAgZ2dwbG90KGFlcyh4PU9ic2VydmVkLCB5PSBQcmVkaWN0ZWQsIA0KICAgICAgICAgIGNvbG91cj0gZmFjdG9yKE5hbWUpKSkgKw0KICBnZW9tX3BvaW50KHNpemU9MykrdGhlbWVfYncoKSsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBsaW5ldHlwZSA9IDEsIGNvbG91cj0iZGFya2dyZXkiKSArDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBjb29yZF9maXhlZChyYXRpbyA9IDEpKw0KICBnZ3RpdGxlKCJOb2RlIE51bWJlciIpKw0KICBmYWNldF9ncmlkKEdyb3d0aFNlYXNvbn5Sb3RhdGlvbikrDQogIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpK3hsYWIoIk9ic2VydmVkIikreWxhYigiUHJlZGljdGVkIikrDQogIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDEyKSkrDQogIHRoZW1lKGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDEyKSkNCmBgYA0KDQoNCg0KDQpgYGB7cn0NCm1lcmdlZGYgJT4lDQogICAgZHBseXI6OmZpbHRlcihDb2xsZWN0aW9uPT0iMTk5N18yMDAxIiklPiUNCiAgZHBseXI6OmZpbHRlcihWYXJpYWJsZT09ICJOb2RlTnVtYmVyIikgJT4lIA0KICAgZHBseXI6OmZpbHRlcihXYXRlcj09ICJpcnIiKSU+JQ0KICBkcGx5cjo6ZmlsdGVyKERlZm9saWF0aW9uPT0gIkxMIiklPiUNCiAgZ2dwbG90KGFlcyh4PU9ic2VydmVkLCB5PSBQcmVkaWN0ZWQsIA0KICAgICAgICAgIGNvbG91cj0gZmFjdG9yKE5hbWUpKSkgKw0KICBnZW9tX3BvaW50KHNpemU9MykrdGhlbWVfYncoKSArDQogICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFRSVUUsIGxpbmV0eXBlID0gMSwgY29sb3VyPSJkYXJrZ3JleSIpICsNCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArDQogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkgKw0KICBnZ3RpdGxlKCJOb2RlIE51bWJlciIpICArDQogIGZhY2V0X2dyaWQoR3Jvd3RoU2Vhc29uflJvdGF0aW9uKSsNCiAgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSxsZWdlbmQucG9zaXRpb24gPSAiYmxhbmsiKSt4bGFiKCJPYnNlcnZlZCIpK3lsYWIoIlByZWRpY3RlZCIpKw0KICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxMikpKw0KICB0aGVtZShheGlzLnRpdGxlLnk9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLGNvbG91cj0iYmxhY2siLHNpemUgPSAxMikpDQpgYGANCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQptZXJnZWRmICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIoQ29sbGVjdGlvbj09IjE5OTdfMjAwMSIpJT4lDQogIGRwbHlyOjpmaWx0ZXIoVmFyaWFibGU9PSAiTm9kZU51bWJlciIpICU+JSANCiAgIGRwbHlyOjpmaWx0ZXIoV2F0ZXI9PSAiaXJyIiklPiUNCiAgZHBseXI6OmZpbHRlcihEZWZvbGlhdGlvbj09ICJMTCIpJT4lDQogIGdncGxvdChhZXMoeD1PYnNlcnZlZCwgeT0gUHJlZGljdGVkLCANCiAgICAgICAgICBjb2xvdXI9IGZhY3RvcihOYW1lKSkpICsNCiAgZ2VvbV9wb2ludChzaXplPTMpK3RoZW1lX2J3KCkgKw0KICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBsaW5ldHlwZSA9IDEsIGNvbG91cj0iZGFya2dyZXkiKSArDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBjb29yZF9maXhlZChyYXRpbyA9IDEpICsNCiAgZ2d0aXRsZSgiTm9kZSBOdW1iZXIiKSAgKw0KICAjIGZhY2V0X2dyaWQoLn5Sb3RhdGlvbikgKyAjIFJvdGF0aW9uDQogIGZhY2V0X3dyYXAofkdyb3d0aFNlYXNvbiwgbmNvbCA9IDQpKw0KICB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLGxlZ2VuZC5wb3NpdGlvbiA9ICJibGFuayIpK3hsYWIoIk9ic2VydmVkIikreWxhYigiUHJlZGljdGVkIikrDQogIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDEyKSkrDQogIHRoZW1lKGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3VyPSJibGFjayIsc2l6ZSA9IDEyKSkNCmBgYA0KDQojIyBSTVNFDQoNCmBgYHtyfQ0Kc3RyKG1lcmdlZGYpDQoNCm1lcmdlZGYgJT4lDQogIGRwbHlyOjpmaWx0ZXIoVmFyaWFibGU9PSAiTm9kZU51bWJlciIpICU+JSANCiAgIGRwbHlyOjpmaWx0ZXIoV2F0ZXI9PSAiaXJyIiklPiUNCiAgZHBseXI6OmZpbHRlcihEZWZvbGlhdGlvbj09ICJMTCIpJT4lDQogI2ZpbHRlcihWYXJpYWJsZSA9PSAiTm9kZU51bWJlciIpICU+JQ0KIGZpbHRlcihDb2xsZWN0aW9uIT0iMjAxMF8yMDEyIiklPiUNCiAgbXV0YXRlKFJvdGF0aW9uPSBhcy5mYWN0b3IoUm90YXRpb24pKSU+JQ0KICBtdXRhdGUoR3Jvd3RoU2Vhc29uPWFzLmZhY3RvcihHcm93dGhTZWFzb24pKSU+JQ0KICBncm91cF9ieShJRCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBuID0gbigpLA0KICAgIHIyID0gZ2F1Y2hTdGF0cyhQcmVkaWN0ZWQsT2JzZXJ2ZWQpWzVdLA0KICAjICBybXNlID0gcm91bmQocm1zZShQcmVkaWN0ZWQsT2JzZXJ2ZWQpLDApLA0KICAgIHJfcm1zZSA9IHJvdW5kKHJtc2UoUHJlZGljdGVkLE9ic2VydmVkKS9tZWFuKE9ic2VydmVkKSoxMDAsMSksDQogICAgbnNlID0gcm91bmQoTlNFKFByZWRpY3RlZCxPYnNlcnZlZCksMiksDQogICAgc2IgPSBnYXVjaFN0YXRzKFByZWRpY3RlZCxPYnNlcnZlZClbMV0sDQogIG51ID0gZ2F1Y2hTdGF0cyhQcmVkaWN0ZWQsT2JzZXJ2ZWQpWzJdLA0KICBsYyA9IGdhdWNoU3RhdHMoUHJlZGljdGVkLE9ic2VydmVkKVszXQ0KICApIA0KDQogIA0KYGBgDQoNCg0KDQo=